Trước: Chương 3 – Câu lệnh điều kiện

4. Cấu trúc điều kiện if-else

Câu lệnh if

Câu lệnh if được sử dụng để xem xét việc thực thi một thao tác nào đó dựa trên điều kiện hiện tại.

Cú pháp:

1.	if (biểu_thức_điều_kiện) {
2.	    khối mã được thực thi nếu điều kiện là đúng
3.	}

Câu lệnh if bao gồm một biểu thức điều kiện và một khối lệnh ở trong phần thân của nó. Tại thời điểm thực thi, nếu biểu thức điều kiện trả về kết quả true thì khối lệnh trong phần thân sẽ được thực thi, còn nếu biểu thức điều kiện trả về false thì khối lệnh trong phần thân sẽ được bỏ qua.

>> Xem thêm: TÀI LIỆU LẬP TRÌNH CĂN BẢN – ĐƠN GIẢN, DỄ HỌC!

Ví dụ: 

1.	if(score > 9) {
2.	   classification = "Xuất sắc";
3.	}

Trong đoạn mã này biểu thức điều kiện là score > 9, còn phần thân là classification =  “Xuất sắc”. Khi thực thi chương trình nếu biến score có giá trị lớn hơn 9 thì biến classification sẽ được gán giá trị là “Xuất sắc”, còn nếu biến score có giá trị bằng hoặc nhỏ hơn 9 thì biến classification sẽ không được gán giá trị mới.

Lưu ý: Nếu phần thân chỉ có một câu lệnh duy nhất thì chúng ta có thể không cần viết dấu mở và đóng ngoặc, còn nếu trong trường hợp phần thân có nhiều hơn 1 câu lệnh thì chúng ta bắt buộc phải mở và đóng ngoặc.

Câu lệnh if-else

Câu lệnh if-else là dạng đầy đủ của câu lệnh if.

Cú pháp:

1.	if (biểu_thức_điều_kiện) {
2.	   khối mã được thực thi nếu điều kiện là đúng
3.	} else {
4.	   khối mã được thực thi nếu điều kiện trên là sai
5.	}

Câu lệnh if-else cũng bao gồm một biểu thức điều kiện, nhưng lại có hai phần thân khác nhau. Một phần thân gắn với phần if và một phần thân gắn với phần else.

Nếu biểu thức điều kiện trả về true thì phần thân gắn với if được thực thi, còn nếu biểu thức điều kiện trả về false thì phần thân gắn với phần else được thực thi. Luồng thực thi của câu lệnh if-else có thể được mô tả như lưu đồ dưới đây:




Hình: Luồng thực thi của câu lệnh if-else

Ví dụ 1:

1.	if(hour < 18){
2.	   greeting = "Good day";
3.	}else{
4.	   greeting = "Good evening";
5.	}

Trong đoạn mã trên, biểu thức điều kiện là hour < 18, còn phần thân của ifgreeting = “Good day” và phần thân của elsegreeting = “Good evening”.

Khi thực thi, nếu biến hour có giá trị nhỏ hơn 18 thì biến greeting sẽ được gán giá trị là “Good day”, còn nếu biến hour có giá trị lớn hơn hoặc bằng 18 thì biến greeting sẽ được gán giá trị là “Good evening”.

Ví dụ 2:

1.	if(number % 2 == 0){
2.	   alert(number + " is even.");
3.	}else{
4.	   alert(number + " is odd.")
5.	}

Trong ví dụ trên, chúng ta đánh giá một số nguyên và phân loại số đó là số chẵn hay là số lẻ.

Trong trường hợp này, biểu thức điều kiện là để đánh giá xem số hiện tại có chia hết cho 2 hay không, còn hai phần thân là hiển thị thông báo tương ứng.

Việc đánh giá chia hết cho 2 hay không được thực hiện thông qua phép chia lấy phần dư và sau đó so sánh với giá trị 0. Nếu phần dư bằng không thì chứng tỏ đây là số chẵn, còn nếu phần dư khác 0 thì số đó là số lẻ.

Chẳng hạn, nếu number có giá trị là 4 thì kết quả phép chia cho 2 lấy phần dư là 0, do vậy biểu thức điều kiện sẽ trả về đúng, và phần thân của if được thực thi.

Nếu number có giá trị là 5 thì kết quả phép chia cho 2 lấy phần dư là 1, do vậy biểu thức điều kiện trả về sai, phần thân của else được thực thi.

if-else với một dòng lệnh bên trong

Trong trường hợp chỉ có một dòng lệnh bên trong if hoặc else thì có thể bỏ dấu ngoặc.

Ví dụ:

1.	if(number % 2 == 0)
2.	  alert(number + " is even.");
3.	else
4.	  alert(number + " is odd.")

5. Cấu trúc điều kiện if-else lồng nhau

Ngoài việc sử dụng câu lệnh if-else riêng lẻ, chúng ta cũng có thể đặt câu lệnh if-else này trong câu lệnh if-else khác. Điều này xảy ra khi chúng ta muốn đánh giá nhiều biểu thức điều kiện trước khi thực thi một thao tác nào đó.

Cú pháp:

1.	if (điều kiện 1) {
2.	     //khối lệnh thực thi nếu điều kiện 1 đúng
3.	     if (điều kiện 2) {
4.	          //khối lệnh thực thi nếu điều kiện 2 đúng
5.	     } else {
6.	          //khối lệnh thực thi nếu điều kiện 2 sai
7.	     }
8.	} else {
9.	     //khối lệnh thực thi nếu điều kiện 1 sai
10.	}

Ví dụ:

1.	if (a > b) {
2.	   if (a > c) {
3.	       console.log("Số lớn nhất là a = " + a);
4.	   } else {
5.	       console.log("Số lớn nhất là c = " + c);
6.	   }
7.	} else {
8.	   if (b > c) {
9.	       console.log("Số lớn nhất là b = " + b);
10.	  } else {
11.	      console.log("Số lớn nhất là c = " + c);
12.	   }
13.	}

Trong ví dụ này, chúng ta so sánh các giá trị của 3 biến là a, b và c để tìm ra giá trị lớn nhất trong 3 số đó. Chúng ta cần đặt các câu lệnh điều kiện bên trong các câu lệnh điều kiện khác.

Chẳng hạn, với trường hợp a = 5, b = 4, c = 3 thì biểu thức a > b sẽ trả về kết quả true, do đó phần thân của lệnh if này được thực thi, phần thân của lệnh else tương ứng sẽ được bỏ qua. Sau đó, biểu thức a > c cũng trả về kết quả true, do đó phần thân của câu lệnh if này cũng sẽ được thực thi, và phần thân của câu lệnh else tương ứng sẽ được bỏ qua. Như vậy, chuỗi in ra sẽ là “Số lớn nhất là a = 5”.

Hỏi nhanh: Hãy thử suy luận để xem luồng thực thi của đoạn mã trên sẽ là như thế nào trong trường hợp a = 3, b = 4, c = 5.

6. Cấu trúc điều kiện if-else bậc thang

Khi chúng ta kết hợp nhiều câu lệnh if-else liên tiếp nhau theo dạng if-else-if thì chúng ta được một dạng mới thường được gọi là câu lệnh điều kiện if-else bậc thang. Gọi là bậc thang bởi vì khi viết chúng được trình bày dạng như các bậc thang hướng từ trên xuống dưới.

Các khối lệnh điều kiện được đặt trong các câu lệnh if nối tiếp nhau, nếu một điều kiện nào đó thoả mãn thì khối lệnh trong thân câu lệnh if sẽ được thực thi, còn nếu điều kiện sai thì sẽ chuyển sang đánh giá điều kiện if tiếp theo cho đến khi kết thúc.

Luồng thực thi của khối lệnh if-else bậc thang có thể mô tả như lưu đồ sau:

Cú pháp:

1.	if (điều kiện 1) {
2.	   //khối mã được thực thi nếu điều kiện 1 là đúng
3.	} else if (điều kiện 2) {
4.	   //khối mã được thực thi nếu điều kiện 1 là sai và điều kiện 2 là đúng
5.	} else {
6.	   //khối mã được thực thi nếu điều kiện 1 và điều kiện 2 đều sai
7.	}

Ví dụ:

1.	if(time < 10){
2.	   greeting = "Good morning";
3.	}else if(time < 20){
4.	   greeting = "Good day";
5.	}else{
6.	   greeting = "Good evening";
7.	}

Trong ví dụ này, nếu giá trị của time là 9 thì điều kiện đầu tiên đúng, do đó biến greeting sẽ có giá trị là “Good morning”.

Nếu giá trị của time là 11 thì điều kiện đầu tiên không đúng, do đó chuyển sang đánh giá điều kiện của câu lệnh if tiếp theo, ở đây điều kiện time < 20 là đúng, do đó biến greeting sẽ được gán giá trị là “Good day”.

Nếu giá trị của biến time là 21 thì điều kiện đầu tiên không đúng, chuyển sang đánh giá điều kiện thứ hai cũng không đúng, do đó chuyển đến thực thi câu lệnh else cuối cùng, và kết quả biến greeting sẽ được gán giá trị là “Good evening”.

7. Cấu trúc điều kiện switch-case

Câu lệnh switch-case là một bộ lựa chọn đa hướng, nó so sánh giá trị của một biểu thức với một danh sách các hằng số nguyên hoặc hằng ký tự. Chúng ta sử dụng câu lệnh switch-case trong những trường hợp muốn phân loại luồng thực thi của chương trình dựa vào các điều kiện so sánh bằng. Khi biểu thức so sánh bằng trả về đúng thì khối lệnh tương ứng được thực thi.

Cú pháp:

1.	switch (param) {
2.	   case value1:
3.	       //khối lệnh 1
4.	   case value2:
5.	       //khối lệnh 2
6.	   case value3:
7.	       //khối lệnh 3
8.	   default:
9.	       //Khối lệnh mặc định sẽ được thực thi nếu không chọn được khối lệnh nào khác
10.	}

Trong đó param là một biểu thức. Trình thực thi sẽ so sánh giá trị của param lần lượt với giá giá trị đi theo sau các case. Nếu gặp một case mang theo giá trị bằng với giá trị của param thì các khối lệnh đi sau đó sẽ được thực thi.

Trong trường hợp không tìm thấy case nào mang giá trị khớp với param thì khối lệnh đi theo sau default sẽ được thực thi. default là một khối lệnh không bắt buộc.

Lưu ý: Cho dù là thực thi mã đi theo case hay default, lệnh switch sẽ còn tiếp tục thực thi mã của tất cả các case (hay cả mã của default) đứng sau đó, mà không cần xem xét bất cứ điều kiện gì. Quá trình đó có thể được biểu diễn bằng lưu đồ như sau:




<!– /* Font Definitions */ @font-face {font-family:”Cambria Math”; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-536869121 1107305727 33554432 0 415 0;} @font-face {font-family:”Open Sans”; panose-1:2 11 6 6 3 5 4 2 2 4; mso-font-alt:Arial; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-536870161 1073750107 40 0 415 0;} @font-face {font-family:”Myriad Pro”; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-alt:Calibri; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:536871559 1 0 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:””; margin-top:0cm; margin-right:0cm; margin-bottom:6.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:12.0pt; font-family:”Myriad Pro”,sans-serif; mso-fareast-font-family:”Open Sans”; mso-bidi-font-family:”Open Sans”; mso-no-proof:yes;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:12.0pt; mso-ansi-font-size:12.0pt; mso-bidi-font-size:12.0pt; font-family:”Calibri”,sans-serif; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:”Times New Roman”; mso-bidi-theme-font:minor-bidi; mso-ansi-language:#1000;} @page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 72.0pt 72.0pt 72.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} –>
Chúng ta có thể thấy luồng thực thi nối thẳng từ khối lệnh này tới khối lệnh khác mà không thông qua bất kỳ khối hình thoi (khối xét điều kiện) nào. Vì hình ảnh này mà tính chất thực thi này được gọi là fall-though (rơi xuyên qua) trong tiếng Anh.

Ví dụ:

1.	let switcher = 1;
2.	switch (switcher) {
3.	 case 0:
4.	   alert("Đèn sáng");
5.	 case 1:
6.	   alert("Đèn tắt");
7.	 default:
8.	   alert("Không tìm thấy công tắc");
9.	}

Mặc dù chỉ có một case mang giá trị khớp với switcher, trình duyệt sẽ thực thi mã của cả case 1 lẫn default, và kết quả là trình duyệt sẽ hiển thị 2 thông báo alert thay vì chỉ 1.

Từ khóa break

Chúng ta có thể ứng dụng sự đặc biệt trong cách thực thi của lệnh switch để dùng chung mã giữa các case, nhờ đó tạo ra được những lệnh switch ngắn gọn. Tuy nhiên để khắc phục hiện tượng luồng thực thi rơi xuyên qua tất cả các case phía sau, thay vì chỉ thực thi những mã cần thiết, chúng ta cần vận dụng từ khóa break.

Từ khóa break sẽ làm luồng thực thi ngay lập tức thoát ra khỏi câu lệnh switch hiện tại.

Từ khóa break thường được đặt làm câu lệnh cuối cùng của mỗi case, nhờ thế, hiện tượng rơi được khắc phục.

Ví dụ:

1.	let switcher = 0;
2.	switch (switcher) {
3.	   case 0:
4.	       alert("Đèn sáng");
5.	       break;
6.	   case null:
7.	   case undefined:
8.	       alert("Không tìm thấy công tắc");
9.	   case 1:
10.	   default:
11.	       alert("Đèn tắt");
12.	}

Nhờ có break, giờ đây chỉ có alert “Đèn sáng” hiện lên. Nhờ sự rơi, nếu switcher  mang giá trị là 1 thì alert “Đèn tắt” vẫn hiện lên. Nếu chúng ta thực thi đoạn mã trên với giá trị switchernull hay undefined, sẽ có 2 alert hiện lên.

Lưu ý:

Lệnh switch khớp giá trị của param với các case bằng toán tử === chứ không phải ==.

Ví dụ:

1.	let switcher = "0";
2.	switch (switcher) {
3.	   case 0:
4.	       alert("Đèn sáng");
5.	       break;
6.	   case null:
7.	   case undefined:
8.	       alert("Không tìm thấy công tắc");
9.	   case 1:
10.	   default:
11.	       alert("Đèn tắt");
12.	}

Đoạn mã trên sẽ khớp giá trị của switcher với case default thay vì case 0 như chúng ta thường nghĩ.

Bài tập thực hành và lời giải