Cấu trúc của một câu lệnh if
Câu lệnh if chỉ chạy một khối code khi điều kiện đúng. Cấu trúc gồm một từ khóa, một điều kiện trong cặp ngoặc tròn và một khối lệnh trong cặp ngoặc nhọn:
Điều kiện age >= 18 cho kết quả true, nên khối lệnh được chạy. Nếu age là 16, điều kiện sẽ là false và JavaScript bỏ qua hoàn toàn khối lệnh.
Về kỹ thuật, cặp ngoặc nhọn có thể bỏ khi khối lệnh chỉ có một câu lệnh, nhưng hãy luôn viết chúng. Câu lệnh if không có ngoặc nhọn là nguồn bug kinh điển khi sau này ai đó thêm dòng thứ hai mà quên rằng dòng đó thật ra không nằm trong khối lệnh.
else: nhánh dự phòng
Ghép if với else để chạy code khác khi điều kiện sai:
Chỉ đúng một trong hai nhánh được chạy. Không bao giờ cả hai, cũng không bao giờ không nhánh nào. else không có điều kiện riêng: nó là nhánh bắt mọi trường hợp "if sai".
else if: chọn giữa nhiều khả năng
Khi có nhiều hơn hai trường hợp, hãy nối chúng bằng else if. JavaScript kiểm tra lần lượt từng điều kiện và dừng ở điều kiện đúng đầu tiên:
Chỉ một nhánh được chạy. Khi một điều kiện khớp, các điều kiện còn lại bị bỏ qua, kể cả khi chúng cũng đúng. Vì vậy thứ tự rất quan trọng: nếu bạn đảo chuỗi để kiểm tra score >= 60 trước, mọi người trên 60 điểm đều sẽ nhận điểm D.
else cuối cùng là tùy chọn, nhưng có nó thì ý định của bạn rõ ràng hơn: "nếu không có gì khớp, hãy làm việc này".
Điều kiện có thể là bất kỳ biểu thức nào
Thứ nằm trong cặp ngoặc tròn không nhất thiết phải là phép so sánh. Nó có thể là bất kỳ biểu thức nào, JavaScript sẽ chuyển kết quả thành boolean:
Chuỗi không rỗng là truthy. 0 và chuỗi rỗng là falsy, nên khi items.length bằng 0, code đi vào nhánh else. Đây là cách viết chuẩn trong JavaScript để "kiểm tra xem có gì ở đó không".
Danh sách giá trị falsy rất ngắn và đáng để thuộc lòng: false, 0, -0, 0n, "", null, undefined và NaN. Mọi thứ khác đều là truthy, kể cả "0", "false", [] và {}. Hai giá trị cuối hay khiến người ta vấp.
Kết hợp điều kiện: && và ||
Dùng && (và) và || (hoặc) để kết hợp các điều kiện:
&& yêu cầu cả hai vế đều truthy. || chỉ cần ít nhất một vế. Cả hai đều đánh giá ngắn mạch (short-circuit): && dừng ở giá trị falsy đầu tiên, || dừng ở giá trị truthy đầu tiên. Điều này quan trọng khi điều kiện thứ hai có tác dụng phụ hoặc có thể ném lỗi: user && user.name trả về undefined một cách an toàn nếu user là null, không làm chương trình sập.
Bọc logic hỗn hợp trong cặp ngoặc tròn để thứ tự ưu tiên rõ ràng:
Không có ngoặc, && được ưu tiên cao hơn ||, thường là ngược với cách bạn đọc tự nhiên.
== và === (hãy dùng ===)
Khi kiểm tra bằng nhau bên trong if, hãy dùng === và !==, không dùng == và !=:
== chuyển kiểu trước khi so sánh, dẫn đến những bất ngờ như "" == 0 là true và null == undefined là true. === so sánh mà không chuyển kiểu: cùng kiểu và cùng giá trị. Hãy mặc định dùng ===. Ngoại lệ phổ biến duy nhất là x == null, kiểm tra cả null lẫn undefined trong một lần.
Toán tử ba ngôi
Để chọn giữa hai giá trị, toán tử ba ngôi (ternary operator) condition ? a : b thường gọn hơn một câu lệnh if/else đầy đủ:
Toán tử ba ngôi là một biểu thức: nó tạo ra một giá trị. Đó là điểm khác biệt chính so với if/else, vốn là một câu lệnh. Dùng toán tử ba ngôi khi bạn cần kết quả (gán biến, trả về, ghép chuỗi). Dùng if/else khi bạn chạy các tác dụng phụ.
Bạn có thể nối nhiều toán tử ba ngôi, nhưng code sẽ khó đọc hẳn:
// Don't do this:
const grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
Nếu phải nối chuỗi như vậy, hãy quay về else if.
if lồng nhau và else if phẳng
Đôi khi một điều kiện chỉ có nghĩa khi nằm trong một điều kiện khác. Lồng nhau trong trường hợp đó là ổn:
Nhưng lồng sâu ba, bốn tầng là dấu hiệu code có vấn đề. Hãy làm phẳng nó bằng return sớm hoặc một điều kiện kết hợp:
Return sớm giúp mỗi nhánh ngắn gọn và nằm cùng một mức thụt lề. Dễ đọc lướt hơn nhiều so với một kim tự tháp if lồng nhau.
Lỗi thường gặp: phép gán bên trong if
= là gán. === là so sánh. Nhầm hai thứ này bên trong một điều kiện là bug kinh điển:
status = "done" gán "done" cho status và cho ra giá trị "done", vốn là truthy, nên khối lệnh luôn chạy và bạn đã âm thầm ghi đè biến. Các linter sẽ bắt được lỗi này. Strict mode thì không. Hãy cẩn thận, và dùng === khi bạn muốn so sánh.
Tiếp theo: switch
Khi so sánh một giá trị với nhiều khả năng khớp, chuỗi else if dài bắt đầu trở nên lặp lại. Câu lệnh switch của JavaScript được làm ra chính cho trường hợp đó, và nó có những điểm đặc biệt riêng về break và fall-through, là nội dung của trang tiếp theo.
Câu hỏi thường gặp
Viết câu lệnh if/else trong JavaScript như thế nào?
Đặt điều kiện trong cặp ngoặc tròn sau if, rồi đến một khối lệnh trong cặp ngoặc nhọn. Tiếp theo là else và một khối lệnh khác cho trường hợp còn lại. Ví dụ: if (age >= 18) { console.log('adult'); } else { console.log('minor'); }. Điều kiện có thể là bất kỳ biểu thức nào, JavaScript sẽ chuyển nó thành boolean.
else if và if lồng nhau trong JavaScript khác nhau thế nào?
else if nối các điều kiện thành chuỗi để chỉ một nhánh được chạy: JavaScript kiểm tra lần lượt từng điều kiện và dừng ở điều kiện đúng đầu tiên. Các câu lệnh if lồng nhau đặt câu lệnh này vào trong câu lệnh kia, thường để chỉ kiểm tra điều kiện thứ hai khi điều kiện thứ nhất đúng. Chuỗi else if phẳng gần như luôn dễ đọc hơn nhiều tầng if lồng nhau.
Khi nào nên dùng toán tử ba ngôi thay cho if/else?
Dùng toán tử ba ngôi condition ? a : b khi bạn chọn giữa hai giá trị trong một biểu thức: gán biến, trả về từ hàm, ghép chuỗi. Hãy giữ if/else khi các nhánh chạy câu lệnh có tác dụng phụ, hoặc khi một trong hai vế dài hơn một biểu thức ngắn. Toán tử ba ngôi lồng nhau rất nhanh trở nên khó đọc.
Vì sao if (0) hoạt động khác if (false) trong JavaScript?
Thật ra không khác: cả hai đều bỏ qua khối lệnh. JavaScript chuyển điều kiện thành boolean, và 0, '', null, undefined, NaN và false đều là falsy. Cái bẫy nằm ở chỗ những giá trị như '0' (một chuỗi không rỗng) và [] (một mảng rỗng) lại là truthy, điều khiến người đến từ ngôn ngữ khác bất ngờ.