Câu 1console.log("0" === 0); hiển thị gì?
Boolean và So Sánh — Khác Biệt Giữa == và ===
Học so sánh trong JavaScript: khác biệt giữa === và ==, cách dựng điều kiện, 6 giá trị falsy, và mặc định với ||.
Đơn hàng đã đủ điều kiện miễn phí vận chuyển chưa? Người dùng đã đăng nhập chưa? Kho còn hàng không? Việc thay đổi nội dung hiển thị trên màn hình luôn bắt đầu từ chỗ kiểm tra một điều kiện có đúng hay không.
Bài này nói về khác biệt giữa === và == khi kiểm tra hai giá trị có bằng nhau, về toán tử so sánh và toán tử logic dùng để dựng nên điều kiện, và về 6 giá trị falsy (giá trị được coi như false khi đặt trong một điều kiện) mà JavaScript xem là "không đúng".
Kiểm Tra Bằng Nhau — Khác Biệt Giữa === và ==
Hãy hình dung bạn cần so khớp giá trị người dùng gõ vào ô nhập với giá trị hệ thống đã lưu sẵn. Nhìn thì giống nhau — cùng là 0 — nhưng giá trị lấy từ ô nhập là chuỗi "0", còn giá trị đã lưu là số 0.
Để quyết định có coi hai giá trị này là "bằng nhau" hay không, JavaScript có hai toán tử.
=== chỉ trả về true khi cả kiểu lẫn giá trị đều giống nhau. Kiểu khác nhau là ra false ngay tại đó.
Còn == thì chuyển kiểu của một vế cho khớp với vế kia trước, rồi mới so sánh giá trị. "0" và 0 cho false với === nhưng cho true với ==. Phía "không bằng nhau" cũng có hai toán tử: !== và !=.
=== thấy khác kiểu là trả về false ngay; == thì đưa hai vế về cùng kiểu trước rồi mới so sánh giá trị.Chuyển đổi (conversion) ở đây nghĩa là đọc ký tự "0" thành số 0. Vấn đề là == ngầm chèn thêm bước chuyển đổi này trước khi so sánh.
Vì nó so sánh các giá trị đã được chuyển đổi, kết quả không đúng như những gì bạn viết ra. Có những giá trị nhìn hoàn toàn khác nhau, như chuỗi rỗng "" và 0, mà vẫn cho ra true.
Kiểu nào được chuyển sang kiểu nào thì mỗi tổ hợp đều có quy tắc cố định, nhưng thay vì học thuộc các quy tắc đó, dùng === để không cho việc chuyển đổi xảy ra sẽ giúp bạn theo dõi kết quả dễ hơn. Với code viết mới, hãy dùng === và !==, và đưa các giá trị về cùng kiểu trước khi so sánh. Chuyển đổi diễn ra theo hướng nào, và cách tự đưa các giá trị về cùng kiểu, sẽ được nói ở bài tiếp theo về chuyển đổi kiểu.
== so sánh các giá trị sau khi đã chuyển đổi, nên kết quả không đúng như những gì bạn viết ra. Với === thì không có chuyển đổi nào xảy ra. Hướng chuyển đổi sẽ được nói ở bài tiếp theo.const typedQuantity = "3"; // số lượng gõ vào ô nhập (chuỗi)
const savedQuantity = 3; // số lượng đã lưu (số)
console.log(typedQuantity === savedQuantity); // false kiểu khác nhau
console.log(typedQuantity == savedQuantity); // true đưa về cùng kiểu rồi so sánh
// Cùng kiểu thì === cũng so sánh bình thường
console.log(savedQuantity === 3); // true
console.log(savedQuantity !== 3); // false phủ định của ===
console.log("" == 0); // true chuỗi rỗng cũng được chuyển thành 0
console.log("100" === 100); // false === không bao giờ chuyển đổi
Xây Dựng Điều Kiện — Toán Tử So Sánh và Toán Tử Logic
Trong thực tế, chỉ hỏi "hai giá trị này có bằng nhau không" là chưa đủ. Bạn sẽ cần những điều kiện như "tổng tiền có từ 5000 trở lên không" hay "vừa đã đăng nhập vừa là admin".
So sánh lớn nhỏ là việc của toán tử so sánh (ký hiệu dùng để xét quan hệ giữa hai giá trị — === ở phần trước cũng thuộc nhóm này), còn nối nhiều điều kiện lại với nhau là việc của toán tử logic (ký hiệu kết hợp các giá trị boolean).
Toán tử so sánh có 4 cái — > < >= <= — và kết quả luôn là true hoặc false.
Toán tử logic có 3 cái. && chỉ true khi cả hai vế đều true, || true khi một trong hai vế true, còn ! thì đảo true thành false và ngược lại.
&& thu hẹp điều kiện, || mở rộng nó, và ! đảo ngược kết quả.Điều kiện bạn dựng lên sẽ được truyền cho câu lệnh if (cấu trúc chỉ chạy khối lệnh phía sau khi điều kiện trong dấu ngoặc là true). Phần cần chạy khi điều kiện là false thì viết trong khối sau else.
Ở bài này ta chỉ dùng if để kiểm tra kết quả của một điều kiện — cách nối tiếp nhiều else if và cách rẽ nhánh bằng switch sẽ được nói ở bài về câu điều kiện trong nhóm cú pháp.
const cartTotal = 4800; // tổng giỏ hàng
const hasCoupon = true; // có mã giảm giá không
const isMember = false; // có phải thành viên không
console.log(cartTotal >= 5000); // false chưa đạt 5000
console.log(cartTotal < 5000); // true
console.log(hasCoupon && isMember); // false không phải thành viên
console.log(hasCoupon || isMember); // true nhưng có mã giảm giá
console.log(!isMember); // true đảo false
if (cartTotal >= 5000) {
console.log("Miễn phí vận chuyển"); // chỉ chạy khi điều kiện true
} else {
console.log(`Còn thiếu ${5000 - cartTotal} nữa là được miễn phí vận chuyển`); // false thì chạy nhánh này
}
Truthy và Falsy — Những Giá Trị if Coi Là False
Trong dấu ngoặc của if, bạn viết được cả những giá trị khác ngoài true / false. Khi đó JavaScript sẽ quy giá trị được đưa vào về một trong hai nhóm đúng hoặc sai.
Giá trị bị coi là false gọi là falsy, còn lại là truthy (giá trị được coi như true khi đặt trong một điều kiện). Số giá trị falsy bạn gặp trong điều kiện chỉ có 6, nên nhớ 6 giá trị này là có thể coi mọi thứ còn lại đều truthy.
6 giá trị đó là false, số 0, chuỗi rỗng "", null (giá trị được gán một cách chủ ý để thể hiện là không có gì), undefined (giá trị cho biết chưa có gì được gán vào) và NaN. Khi nào dùng null, khi nào dùng undefined sẽ được giải thích ở bài sau.
Khi viết code, bạn gặp nhiều nhất là 0 và "", nên nhớ trước hai giá trị này là đủ. Riêng NaN là ngoại lệ — so nó với chính nó bằng === vẫn ra false — nên muốn kiểm tra NaN bạn phải dùng một cách viết riêng.
Hai giá trị dễ gây vấp nhất là số 0 và chuỗi rỗng.
Khi số lượt đánh giá là 0, hay ô tìm kiếm bỏ trống nên là "", nếu bạn đưa thẳng giá trị đó vào if thì điều kiện sẽ không đúng. Bạn định hỏi "có giá trị hay không", nhưng thực tế câu lệnh lại đang hỏi "có khác 0 và khác rỗng hay không".
const reviewCount = 0; // số lượt đánh giá
const searchWord = ""; // văn bản gõ vào ô tìm kiếm
if (reviewCount) {
console.log("Có đánh giá");
}
if (searchWord) {
console.log("Có từ khóa tìm kiếm");
}
// 0 và chuỗi rỗng đều falsy nên cả hai khối trên đều không chạy
if (reviewCount === 0) {
console.log("Chưa có đánh giá"); // cái này chạy
}
Viết Rõ Điều Kiện Khi 0 Là Giá Trị Có Ý Nghĩa
Với những giá trị mà bản thân số 0 đã có ý nghĩa — số lượng tồn kho, số lượt, số tiền — nếu viết if (stock) thì đúng lúc bằng 0 khối lệnh lại bị bỏ qua. Viết rõ điều bạn thực sự muốn kiểm tra, như stock > 0 hay stock === 0, thì người đọc cũng nắm được ý định của bạn.
Short-Circuit Evaluation — Đặt Giá Trị Mặc Định Bằng ||
Với cả những người dùng đăng ký mà không điền tên hiển thị, màn hình vẫn phải hiện ra một cái tên nào đó. Kiểu xử lý "không có giá trị thì dùng giá trị mặc định" này viết gọn được trong một dòng bằng ||.
Sở dĩ viết được như vậy là vì && và || không tạo ra một giá trị boolean — chúng trả về nguyên giá trị của vế trái hoặc vế phải. Khi bạn kết hợp các giá trị true và false với nhau thì kết quả vẫn là true hoặc false, nên không mâu thuẫn với những gì đã học ở trên.
|| trả về nguyên giá trị vế trái nếu vế đó truthy, và thậm chí không đánh giá vế phải. Chỉ khi vế trái falsy nó mới trả về giá trị vế phải.
&& thì ngược lại — nếu vế trái falsy, nó trả về luôn giá trị vế trái đó mà không đánh giá vế phải. Cách hoạt động "chưa cần thì chưa đụng tới vế phải" này gọi là short-circuit evaluation (không đánh giá vế phải khi một mình vế trái đã đủ quyết định kết quả).
const nickname = ""; // để trống
// || chỉ trả về vế phải khi vế trái falsy
console.log(nickname || "Guest"); // Guest
console.log("Bob" || "Guest"); // Bob vế phải không được đánh giá
// && nếu vế trái falsy thì trả về luôn vế trái, không đánh giá vế phải
console.log(0 && "còn hàng"); // 0
console.log(5 && "còn hàng"); // còn hàng
|| Không Đủ Khi Bạn Muốn Giữ 0 hoặc Chuỗi Rỗng
|| thay mọi giá trị falsy bằng giá trị mặc định, nên cả những giá trị falsy có ý nghĩa cũng biến mất — điểm tích lũy bằng 0, hay chuỗi "0" mà người dùng vừa gõ vào. Muốn chỉ dùng giá trị mặc định khi giá trị là null hoặc undefined, bạn dùng một toán tử riêng là ??; bài 9 sẽ nói về toán tử này.
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2Giá trị nào dưới đây không phải falsy?
Câu 3console.log(0 || 100); hiển thị gì?