Câu 1Trong một chuỗi else if đặt >= 50000 trước và >= 100000 sau, khi truyền vào 120000 thì nhánh nào chạy?
Rẽ nhánh điều kiện — else if, toán tử ba ngôi và switch
Học rẽ nhánh trong JavaScript từ nền tảng: else if để xét lần lượt từng bậc, toán tử ba ngôi trả về giá trị, và switch cùng vai trò của break.
Khi xác định hạng thành viên hay hiển thị trạng thái đơn hàng, điều kiện hiếm khi chỉ chia đôi gọn gàng. Nếu viết ba hạng Platinum, Gold và Regular bằng ba câu if riêng lẻ, các điều kiện bên dưới vẫn bị kiểm tra dù điều kiện phía trên đã cho ra kết quả, và số dòng in ra sẽ tùy vào số điều kiện đúng.
Bài này nói về else if để xét điều kiện theo từng bậc, toán tử ba ngôi trả về thẳng một giá trị, và switch để so một giá trị với nhiều ứng viên.
Chia thành ba trường hợp trở lên — nối tiếp else if
Giả sử bạn gán nhãn đánh giá dựa trên điểm trung bình của các review sản phẩm: từ 4.5 trở lên là "Rất tốt", từ 3.5 trở lên là "Tốt", thấp hơn nữa là "Chưa tốt".
Hai câu if đặt cạnh nhau được kiểm tra độc lập với nhau, nên với điểm 4.8 thì cả hai điều kiện đều đúng và màn hình in ra hai dòng: "Rất tốt" và "Tốt".
Khi nối tiếp bằng else if (điều kiện kế tiếp, chỉ được kiểm tra khi điều kiện trước đó sai), nhiều điều kiện gộp lại thành một cấu trúc rẽ nhánh duy nhất. Khối { } đi sau mỗi điều kiện được gọi là một nhánh.
Các điều kiện được kiểm tra từ trên xuống, và chỉ nhánh có điều kiện đúng đầu tiên được chạy. Nếu không điều kiện nào đúng, nhánh else sẽ chạy.
const score = 4.8; // điểm review trung bình của sản phẩm
// Các câu if đặt cạnh nhau được kiểm tra độc lập
if (score >= 4.5) {
console.log("Rất tốt"); // đúng
}
if (score >= 3.5) {
console.log("Tốt"); // cũng đúng → in ra 2 dòng
}
// Nối bằng else if thì việc rẽ nhánh dừng ở nhánh đúng đầu tiên
if (score >= 4.5) {
console.log("Rất tốt"); // chỉ nhánh này chạy
} else if (score >= 3.5) {
console.log("Tốt"); // không được kiểm tra
} else {
console.log("Chưa tốt"); // không được kiểm tra
}
Điểm 4.8 thỏa score >= 4.5 ngay ở bậc đầu và đi sang phải, nên bậc thứ hai không được kiểm tra. Mũi tên chỉ đi xuống bậc tiếp theo khi điều kiện sai.
Bạn có thể bỏ else. Khi không có else và không điều kiện nào đúng, sẽ không nhánh nào chạy và chương trình đi tiếp xuống dòng nằm sau cả cấu trúc rẽ nhánh.
Bảng dưới đây cho thấy việc kiểm tra dừng ở bậc nào khi đưa ba mức điểm khác nhau qua cùng một chuỗi else if.
| Điểm trung bình | Kiểm tra từ trên xuống | Dòng được in ra |
|---|---|---|
| 4.8 | Từ 4.5 trở lên là đúng, dừng tại đây | Rất tốt (chỉ 1 dòng) |
| 3.8 | Từ 4.5 trở lên là sai / từ 3.5 trở lên là đúng | Tốt (chỉ 1 dòng) |
| 2.1 | Cả hai đều sai nên xuống nhánh else | Chưa tốt (chỉ 1 dòng) |
Thứ tự viết điều kiện làm thay đổi kết quả
Nếu đặt điều kiện bao phủ khoảng rộng lên trước, các điều kiện hẹp hơn bên dưới sẽ không bao giờ được xét tới. Nếu viết score >= 3.5 trước, sản phẩm được 4.8 điểm cũng bị chốt là "Tốt". Muốn 4.8 điểm là "Rất tốt", bạn đặt điều kiện hẹp hơn như score >= 4.5 lên trước.
Nhận kết quả dưới dạng giá trị — cách viết toán tử ba ngôi
Có lúc bạn muốn chuyển qua lại giữa "Còn hàng" và "Hết hàng" theo số lượng tồn kho, rồi lưu chuỗi đó vào một biến để dùng lại. Nếu viết bằng if và else thì không dùng được const, vì const phải nhận giá trị ngay lúc khai báo. Thay vào đó, bạn phải khai báo biến bằng let trước, rồi gán giá trị trong từng nhánh.
Những đoạn như stock > 0 — khi tính sẽ cho ra một giá trị — được gọi là biểu thức (expression). Còn những đoạn như if (…) { … } — chỉ thực hiện hành động mà không để lại giá trị nào — được gọi là câu lệnh (statement).
Với toán tử ba ngôi (ternary operator — biểu thức nhận ba phần là điều kiện, giá trị khi true và giá trị khi false, rồi trả về chính giá trị được chọn), bạn viết được cả hai nhánh trên một dòng.
const stock = 0; // số lượng tồn kho
// if là câu lệnh nên khai báo và gán giá trị phải tách thành hai bước
let label;
if (stock > 0) {
label = "Còn hàng";
} else {
label = "Hết hàng";
}
console.log(label); // Hết hàng
// Toán tử ba ngôi là biểu thức nên có thể gán thẳng vào const
const badge = stock > 0 ? "Còn hàng" : "Hết hàng";
console.log(badge); // Hết hàng
// Cũng có thể viết thẳng bên trong template literal
console.log(`Trạng thái: ${stock > 0 ? "Có thể mua" : "Chờ nhập hàng"}`); // Trạng thái: Chờ nhập hàng
Khi cần chia thành ba hướng trở lên, hãy quay về dùng else if. Toán tử ba ngôi có thể lồng vào nhau, nhưng khi đó ? và : xuất hiện lặp đi lặp lại trên một dòng như a ? x : b ? y : z, và bạn phải dò bằng mắt xem điều kiện nào đi với giá trị nào.
Rẽ nhánh theo một giá trị — switch và case
Giả sử bạn cần hiển thị thông báo phí tùy theo phương thức thanh toán mà khách hàng đã chọn. Bạn có thể viết bằng else if, nhưng khi đó cùng một biến bị lặp lại nhiều lần — paymentMethod === "credit", paymentMethod === "convenience" — khiến người đọc khó nhận ra cấu trúc rẽ nhánh này đang so sánh cái gì.
Với switch (câu lệnh so một giá trị với nhiều ứng viên theo thứ tự, rồi bắt đầu chạy từ nhánh khớp), bạn chỉ viết giá trị cần so một lần trong cặp ngoặc tròn, rồi liệt kê các ứng viên dưới dạng case giá_trị:. break ở cuối mỗi nhánh sẽ thoát khỏi switch, và khi không có case nào khớp thì nhánh default: sẽ chạy.
const paymentMethod = "credit"; // phương thức thanh toán khách hàng đã chọn
switch (paymentMethod) {
case "credit":
console.log("Miễn phí"); // nhánh này chạy
break;
case "convenience":
console.log("Phí: 200 yên"); // thanh toán tại cửa hàng tiện lợi; không khớp
break;
case "cod":
console.log("Phí: 330 yên"); // thanh toán khi nhận hàng; không khớp
break;
default:
console.log("Hãy chọn cách thanh toán");
}
Bạn có thể bỏ default. Khi switch không có default mà nhận một giá trị không khớp với case nào, sẽ không nhánh nào chạy và chương trình đi tiếp xuống dòng kế tiếp. Nếu có khả năng nhận giá trị nằm ngoài các ứng viên, hãy in một thông báo trong default để thấy ngay trên màn hình khi có giá trị ngoài dự kiến.
case phân biệt chuỗi và số khi so khớp
switch so khớp giống hệt ===, nên khác kiểu là không bao giờ khớp. Chuỗi "200" lấy từ ô nhập sẽ không khớp với case 200: mà đi vào default. Nếu một giá trị có thể là số hoặc chuỗi, hãy chuyển về cùng một kiểu trước khi so khớp.
Chạy tràn xuống case tiếp theo — khi bỏ break
Một chỗ dễ vấp khi dùng switch là quên viết break. Code vẫn đúng cú pháp nên không có lỗi cú pháp nào; bạn chỉ nhận ra khi chạy và thấy màn hình in ra nhiều hơn một dòng.
Khi xảy ra fall-through (vì thiếu break nên code của các case nằm dưới case khớp cũng được chạy tiếp), chương trình cứ thế chạy tiếp — không so sánh với giá trị ghi ở các case bên dưới — cho tới khi gặp break hoặc tới cuối switch.
const orderStatus = "paid"; // trạng thái đơn hàng
// Không có break thì code bên dưới case khớp cũng chạy tiếp
switch (orderStatus) {
case "paid":
console.log("Đã thanh toán"); // khớp, bắt đầu từ đây
case "shipped":
console.log("Đã giao cho vận chuyển"); // không có break nên chạy tiếp
default:
console.log("Vui lòng kiểm tra trạng thái"); // chạy tới tận default
}
// Xếp các case liền nhau để nhiều ứng viên dùng chung một khối code
switch (orderStatus) {
case "pending":
case "paid":
console.log("Chưa gửi hàng"); // cả pending lẫn paid đều vào đây
break;
}
Bạn có thể tận dụng cách hoạt động này khi muốn nhiều ứng viên dùng chung một khối code. Nếu xếp hai nhãn case liền nhau mà không viết code ở giữa, khi khớp với case phía trên, chương trình sẽ đi thẳng xuống code bên dưới. Hãy đặt break ở cuối nhánh dùng chung đó.
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2total >= 5000 ? 0 : 500 trả về gì khi total là 5000?
Câu 3Nếu quên viết break ở cuối một case thì chuyện gì xảy ra?