Nên sử dụng toán tử == hay === trong Javascript?
Bài đăng này đã không được cập nhật trong 3 năm
Thỉnh thoảng, mình hay đọc được mấy bài so sánh vui kiểu trên thế giới có 2 loại người ABC vs XYZ như thế này này Và hồi mới học Javascript mình cũng gặp 2 kiểu so sánh ba bằng "===" và hai bằng "==" trong khi đọc code của mấy anh em đồng dâm, à nhầm đồng trang lứa nhé (kiểu cùng là Beginner ngồi Review chéo Pull Request cho nhau í).
Thôi, bớt lan man, bài viết này mình sẽ đi vào tìm hiểu xem ba bằng và hai bằng khác nhau như thế nào? Và nên sử dụng kiểu so sánh nào?
if (x == y) {
// Kiểu ngưới thứ nhất
}
Hay là
if (x === y) {
// Kiểu người thứ hai
}
Vậy sự khác biệt là gì?
- Đầu tiên, về 1 số thuật ngữ được Javascript định nghĩa thì như sau: Hai bằng (==) được gọi là toán tử so sánh trừu tượng, trong khi Ba bằng (===) được gọi là toán tử so sánh cân bằng nghiêm ngặt. Sự khác biệt giữa chúng có thể được tổng kết như sau: Toán tử so sánh trừu tượng sẽ cố gắng giải quyết các kiểu dữ liệu thông qua việc chuyển đổi kiểu dữ liệu trước khi só sánh, còn toán tử so sánh nghiêm ngặt sẽ trả về false nếu các giá trị khác nhau. Cụ thể, chúng ta nhìn ví dụ dưới đây:
console.log(3 == "3"); // true
console.log(3 === "3"); // false.
- Nhìn vào ví dụ trên, thì toán tử 2 bằng trả về đúng vì chuỗi "3" được chuyển thành số 3 trước khi việc so sánh được thực hiện. Trong khi ba bằng cho thấy rằng đây là 2 kiểu dữ liệu khác nhau nên trả về sai. Khá dễ hiểu phải không, một ví dụ khác nhé
console.log(true == '1'); // true
console.log(true === '1'); // false
- Ta thấy, 1 lần nữa, việc so sánh trừu tượng đã thực hiện chuyển đổi kiểu dữ liệu. Cụ thể là kiểu Boolean True và chuỗi "1" được chuyển đổi thành số 1 và kết quả so sánh là đúng. Còn như bình thường thì so sánh nghiêm ngặt sẽ trả về sai. Nhìn vào 2 ví dụ đơn giản trên, thì chúng ta đã phần nào phân biệt được sự khác nhau giữa ba bằng và hai bằng. Tuy nhiên, trong thực tế có 1 vài trường hợp mà hành vi các toán tử này không trực quan. Chúng ta hãy xem xét 1 số ví dụ khác:
console.log(undefined == null); // true
console.log(undefined === null); // false. Undefined and null are distinct types and are not interchangeable.
console.log(true == 'true'); // false. A string will not be converted to a boolean and vice versa.
console.log(true === 'true'); // false
- Chú ý chút nha, ví dụ dưới dây khá thú vị vì nó mình họa 1 chuỗi bình thường với các đối tượng chuỗi (string object)
console.log("This is a string." == new String("This is a string.")); // true
console.log("This is a string." === new String("This is a string.")); // false
- Và để biết tại sao việc sử dung ba bằng lại trả về sai, chúng ta console lên thử xem thế nào nhé
console.log(typeof "This is a string."); // string
console.log(typeof new String("This is a string.")); //object
- Có thể thấy toán tử mới sẽ luôn trả về 1 đối tượng, và bạn sẽ nhận được kết quả tương tự khi so sánh các số nguyên thủy và các phép toán luận với các hàm bao quanh tương ứng.
Với các toán hạng tham chiếu
- Mở rộng hơn 1 chút, so sánh các toán hạng tham chiếu (so sánh bắc cầu)
- Nói về các đối tượng, điều gì sẽ xảy ra nếu chúng ta muốn so sánh các kiểu tham chiếu? So sánh trừu tượng và nghiêm ngặt sẽ thực hiện khác nhau như thế nào khi chúng ta dùng với các đối tượng?
- Ở đây có 1 quy tắc các bạn cần lưu ý: khi so sánh kiểu bắc cầu thì cả so sánh trừu tượng và so sánh nghiêm ngặt sẽ trả về false, trừ khi cả 2 toán hạng đề cập đến cùng 1 đối tượng chính xác, để làm rõ hơn chúng ta xem ví dụ dưới đây:
var a = [];
var b = [];
var c = a;
console.log(a == b); // false
console.log(a === b); // false
console.log(a == c); // true
console.log(a === c); // true
- Có thể thấy, mặc dù a và b là cùng loại và có giá trị như nhau, nhưng kết quả trả về của cả 2 kiểu so sánh ba bằng và hai bằng đều là false.
Vậy tôi nên sử dụng cái nào?
- Lời khuyên từ các chuyên gia thì chúng ta nên sử dụng toán tử ba bằng, vì theo như những giải thích ở trên thì sử dụng so sánh nghiêm ngặt sẽ làm tăng sự rõ ràng của code của bạn (nhiều lúc không phải vắt óc suy nghĩ hay cố gắng ghi nhớ các quy tắc chuyển đổi kiểu dữ liệu lằng nhằng) và giúp ngăn chặn những sai sót phát sinh từ việc sử dụng so sánh trừu tượng. Nói có sách, mách có chứng, mình xin phép trích lời Nicholas Zakas tác giả cuốn sách JavaScript for Web Developers như sau (xin phép để nguyên bản tiếng Anh để bảo vệ tính nguyên vẹn :man_detective_tone1:) "This helps to maintain data type integrity throughout your code."
- Tuy nhiên, nếu bạn thực sự nắm được vấn đề cốt lõi của 2 loại toán tử này thì việc sử dụng hai bằng hay ba bằng sẽ không còn là vấn đề cần lo lắng nữa ! Kiểu là dù 5 chuông báo thức hay 1 chuông thì cuối cùng bạn vẫn phải đến cty đúng giờ mà thôi =))
- Còn để tốt hơn nữa, khi bạn cần so sánh các giá trị của các loại khác nhau, hãy tự chuyển đổi đưa về cùng kiểu dữ liệu, rồi so sánh => Max rõ ràng =))
Bonus
- Nếu để ý, khi sử dụng toán tử hai bằng, thì toán tử này sẽ cố gắng chuyển đổi kiểu của toán hạng nếu như 2 toán hạng có kiểu khác nhau rồi mới so sánh. Vậy nếu khác nhau thì toán tử nào sẽ lấy làm gốc để thằng kia chuyển đổi về, hay cả 2 cùng về 1 kiểu trung gian? Trình duyệt sẽ giúp các bạn việc chuyển đổi này phải không?
- Thực ra, sự chuyển đổi này khá phức tạp, phạm vi bài viết này mình sẽ khó có thể giải thích hết được =)), nên để có 1 cái nhìn chi tiết hơn mời các bạn có thể tìm hiểu chi tiết hơn tại ECMAScript Language Specification hoặc ở post này
Tài liệu tham khảo
https://www.impressivewebs.com/why-use-triple-equals-javascipt/ https://appendto.com/2016/02/vs-javascript-abstract-vs-strict-equality/
All rights reserved