Chúng ta biết nhiều toán tử so sánh từ toán học.

Trong JavaScript, chúng được viết như thế này:

  • Lớn hơn / ít hơn: a > b, a < b.
  • Lớn hơn / nhỏ hơn hoặc bằng: a >= b, a <= b.
  • Bằng: a == bxin lưu ý dấu bằng bằng ==có nghĩa là kiểm tra đẳng thức, trong khi một số dấu = như a = bcó nghĩa là một phép gán.
  • Không bằng. Trong toán học, ký hiệu là , nhưng trong JavaScript, nó được viết là a != b.

Trong bài viết này, chúng ta sẽ tìm hiểu thêm về các loại so sánh khác nhau, cách JavaScript tạo ra chúng, bao gồm các đặc thù quan trọng.

1. Boolean là kết quả trả về khi so sánh

Tất cả các toán tử so sánh trả về một giá trị boolean:

  • true – có nghĩa là có – đúng
  • false – có nghĩa là không có sự khác biệt, không đúng sự thật.

Ví dụ:

/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/

alert( 2 > 1 );  // true (correct)
alert( 2 == 1 ); // false (wrong)
alert( 2 != 1 ); // true (correct)

Một kết quả so sánh có thể được gán cho một biến, giống như bất kỳ giá trị nào:

let result = 5 > 4; // assign the result of the comparison
alert( result ); // true

2. So sánh chuỗi

Để xem liệu một chuỗi có lớn hơn chuỗi khác hay không, JavaScript sử dụng thứ tự được gọi là dictionary hay lexicographical.

Nói cách khác, các chuỗi được so sánh từng chữ cái.

Ví dụ:

alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true

Thuật toán để so sánh hai chuỗi rất đơn giản:

  1. So sánh ký tự đầu tiên của cả hai chuỗi.
  2. Nếu ký tự đầu tiên từ chuỗi thứ nhất lớn hơn (hoặc ít hơn) so với chuỗi khác, thì chuỗi đầu tiên lớn hơn (hoặc ít hơn) so với chuỗi thứ hai.
  3. Mặt khác, nếu các ký tự đầu tiên của cả hai chuỗi giống nhau, hãy so sánh các ký tự thứ hai theo cùng một cách.
  4. Lặp lại cho đến khi kết thúc một trong hai chuỗi.
  5. Nếu cả hai chuỗi kết thúc ở cùng một độ dài, thì chúng bằng nhau. Nếu không, chuỗi dài hơn là lớn hơn.

Trong các ví dụ ở trên, việc so sánh 'Z' > 'A'đạt được kết quả ở bước đầu tiên trong khi các chuỗi "Glow""Glee"được so sánh theo từng ký tự:

  1. Gcũng giống như G.
  2. lcũng giống như l.
  3. olớn hơn e. Dừng ở đây. Chuỗi đầu tiên là lớn hơn.

Nó không phải là một từ điển thực sự, nhưng nó theo thứ tự của Unicode

Thuật toán so sánh được đưa ra ở trên gần tương đương với thuật toán được sử dụng trong từ điển hoặc danh bạ điện thoại, nhưng nó không hoàn toàn giống nhau.

Ví dụ, trường hợp quan trọng. Một chữ in hoa "A"không bằng chữ thường "a". Cái nào lớn hơn? Chữ thường "a". Tại sao? Bởi vì ký tự chữ thường có chỉ mục lớn hơn trong bảng mã hóa nội bộ mà JavaScript sử dụng (Unicode). Chúng ta sẽ quay lại chi tiết cụ thể và hậu quả của điều này trong Chương chuỗi.

3. So sánh các kiểu khác nhau

Khi so sánh các giá trị của các loại khác nhau, JavaScript chuyển đổi các giá trị thành số.

Ví dụ:

alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1

Đối với các giá trị boolean, truetrở thành 1falsetrở thành 0.

Ví dụ:

alert( true == 1 ); // true
alert( false == 0 ); // true

Một hậu quả buồn cười

Có thể là cùng một lúc:

  • Hai giá trị bằng nhau.
  • Một trong số đó là true và một trong số đó là false.

Ví dụ:

let a = 0;
alert( Boolean(a) ); // false

let b = "0";
alert( Boolean(b) ); // true

alert(a == b); // true!

Từ quan điểm của JavaScript, kết quả này là khá bình thường. Kiểm tra đẳng thức chuyển đổi các giá trị bằng cách sử dụng chuyển đổi số (do đó "0"trở thành 0), trong khi Booleanchuyển đổi rõ ràng sử dụng một bộ quy tắc khác.

4. So sánh ==

Một kiểm tra bình đẳng ==có một vấn đề. Nó không thể phân biệt 0với false:

alert( 0 == false ); // true

Điều tương tự xảy ra với một chuỗi rỗng:

alert( '' == false ); // true

Điều này xảy ra bởi vì toán hạng của các kiểu khác nhau được chuyển đổi thành số bởi toán tử đẳng thức ==. Một chuỗi rỗng, giống như false, trở thành số không.

Phải làm gì nếu chúng tôi muốn phân biệt 0từ false?

Một toán tử đẳng thức nghiêm ngặt ===kiểm tra đẳng thức mà không cần chuyển đổi kiểu.

Nói cách khác, nếu abthuộc các loại khác nhau, thì a === bngay lập tức trả về falsemà không cần chuyển đổi chúng.

Hãy thử nó:

alert( 0 === false ); // false, because the types are different

Ngoài ra còn có một toán tử khắt khe không bình đẳng, !==tương tự !=.

Toán tử so sánh bằng nghiêm ngặt dài hơn một chút để viết, nhưng làm cho nó rõ ràng những gì đang xảy ra và để lại ít lỗi hơn.

5. So sánh với null và không xác định

Có một hành vi không trực quan khi nullhoặc undefinedđược so sánh với các giá trị khác. Đối với một kiểm tra so sánh bình đẳng nghiêm ngặt ===

Các giá trị này là khác nhau, bởi vì mỗi trong số chúng là một kiểu khác nhau.

alert( null === undefined ); // false

Đối với một kiểm tra không nghiêm ngặt ==

Có một quy tắc đặc biệt. Hai người này là một cặp đôi ngọt ngào: họ ngang nhau (theo nghĩa ==).

alert( null == undefined ); // true

Đối với toán học và so sánh khác < > <= >=

null/undefinedđược chuyển đổi thành số: nulltrở thành 0, trong khi undefinedtrở thành NaN.

Bây giờ hãy xem một số điều thú vị xảy ra khi chúng ta áp dụng các quy tắc này. Và, điều quan trọng hơn, làm thế nào để không rơi vào bẫy với chúng.

5.1 Kết quả kỳ lạ: null vs 0

Hãy so sánh nullvới số 0:

alert( null > 0 );  // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true

Về mặt toán học, điều đó thật lạ. Kết quả cuối cùng nói rằng nulllớn hơn hoặc bằng 0, do đó, trong một trong những so sánh ở trên thì phải true, nhưng cả hai đều sai.

Lý do là một kiểm tra bằng ==và so sánh > < >= <=hoạt động khác nhau. So sánh chuyển đổi nullthành một số, coi nó là 0. Đó là lý do tại sao dòng (3) null >= 0là đúng và dòng (1) null > 0là sai.

Mặt khác, việc kiểm tra bình đẳng ==cho undefinednullđược định nghĩa như vậy mà, mà không cần bất kỳ chuyển đổi, họ tương đương với nhau và làm bất cứ điều gì không bằng. Đó là lý do tại sao (2) null == 0là sai.

5.2 Không thể so sánh với không xác định

Giá trị undefinedkhông nên được so sánh với các giá trị khác:

alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)

Tại sao nó không thích số 0 nhiều như vậy? Luôn luôn sai!

Chúng ta nhận được những kết quả này bởi vì:

  • So sánh (1)(2)trả về falseundefinedđược chuyển đổi thành NaNNaNlà một giá trị số đặc biệt trả về falsecho tất cả các so sánh.
  • (3) thànhfalsebởi vì undefinedchỉ bằng null, undefinedvà 0 có giá trị khác.

5.3 Trốn tránh vấn đề

Tại sao chúng ta đi qua những ví dụ này? Chúng ta có nên nhớ những đặc thù này mọi lúc không? Vâng, không thực sự. Trên thực tế, những điều khó khăn này sẽ dần trở nên quen thuộc theo thời gian, nhưng có một cách vững chắc để trốn tránh các vấn đề với chúng:

Chỉ cần đối xử với bất kỳ so sánh với undefined/nullngoại trừ sự bình đẳng nghiêm ngặt ===.

Đừng sử dụng so sánh >= > < <=với một biến có thể null/undefined, trừ khi bạn thực sự chắc chắn về những gì bạn đang làm. Nếu một biến có thể có các giá trị này, hãy kiểm tra chúng một cách riêng biệt.

6. Tóm lược

  • Toán tử so sánh trả về một giá trị boolean.
  • Các chuỗi được so sánh từng chữ cái theo thứ tự từ điển.
  • Khi các giá trị của các kiểu khác nhau được so sánh, chúng sẽ được chuyển đổi thành số (ngoại trừ kiểm tra đẳng thức nghiêm ngặt ===).
  • Các giá trị nullundefinedbằng ==nhau và không bằng bất kỳ giá trị nào khác.
  • Hãy cẩn thận khi sử dụng các so sánh như >hoặc <với các biến đôi khi có thể null/undefined. Kiểm tra null/undefinedriêng là một ý tưởng tốt.

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!