Vòng lặp giúp thực hiện một hành động nhiều lần một cách nhanh chóng và đơn giản. Chương Hướng dẫn JavaScript này giới thiệu về các câu lệnh lặp trong JavaScript.
Hãy tưởng tượng vòng lặp giống như phiên bản vi tính của trò chơi mà bạn bảo một người đi X bước sang một hướng rồi đi Y bước sang một hướng khác; chẳng hạn, ý tưởng trò "Tiến 5 bước về phía Đông" có thể được biểu diễn dưới dạng vòng lặp như sau:
var step;
for (let step = 0; step < 5; step++) {
// Chạy 5 lần, với giá trị chạy từ 0 đến 4.
console.log('Walking east one step');
}
Có nhiều kiểu vòng lặp khác nhau, nhưng tất cả đều thực hiện cùng một việc: làm lại một hành động trong số lần nhất định (số lần đó có thể là 0). Mỗi vòng lặp có các cơ chế khác nhau, tương ứng với đó là sự khác nhau giữa cách xác định điểm bắt đầu và kết thúc của vòng lặp. Tuỳ theo trường hợp xác định mà lựa kiểu vòng lặp cho phù hợp..
Các lệnh lặp trong JavaScript là:
Lệnh for
Vòng lặp for
thực hiện liên tục cho tới khi điều kiện ban đầu trả về false. Vòng for
trong JavaScript tương tự như vòng for
trong Java hoặc C. Lệnh for
có dạng như sau:
for ([biểu_thức_khởi_tạo]; [điều_kiện]; [biểu_thức_tăng_tiến]) lệnh
Vòng lặp for
thực thi như sau:
- Biểu thức khởi tạo (
biểu_thức_khởi_tạo
), nếu có, được thực thi. Biểu thức này thường khởi tạo một hoặc nhiều biến đếm cho vòng lặp, nhưng cú pháp của nó vẫn có thể tạo ra biểu thức có độ phức tạp. Biểu thức này còn có thể khai báo biến. - Biểu thức điều kiện (
điều_kiện
) được tính toán. Nếu giá trị củađiều_kiện
trả về true, các lệnh trong vòng lặp được thực thi. Nếu giá trị củađiều_kiện
trả về false, vòng lặpfor
bị dừng lại. Nếu biểu thứcđiều_kiện
bị khuyết (bỏ qua không đặt), điều kiện sẽ được gán giả định là true. lệnh
sẽ được thực thi. Để thực thi nhiều lệnh, dùng khối lệnh ({ ... }
) để gom nhóm các lệnh này.- Nếu không có lỗi nào xảy ra sau khi thực thi lệnh, biểu thức cập nhật (
biểu_thức_tăng_tiến
) được thực thi. - Quay lại bước 2.
Ví dụ
Hàm dưới đây chứa lệnh for
đếm số option được chọn trong danh sách cuộn (phần tử <select>
cho phép chọn nhiều). Lệnh for
khai báo biến i
và khởi tạo cho nó là 0. Điều kiện kiểm tra i
có nhỏ hơn số option mà phần tử <select>
sở hữu hay không, nếu thoả mãn điều kiện, chương trình sẽ chạy vào lệnh if
, và tăng i
thêm một.
<form name="selectForm">
<p>
<label for="musicTypes">Choose some music types, then click the button below:</label>
<select id="musicTypes" name="musicTypes" multiple="multiple">
<option selected="selected">R&B</option>
<option>Jazz</option>
<option>Blues</option>
<option>New Age</option>
<option>Classical</option>
<option>Opera</option>
</select>
</p>
<p><input id="btn" type="button" value="How many are selected?" /></p>
</form>
<script>
function howMany(selectObject) {
var numberSelected = 0;
for (var i = 0; i < selectObject.options.length; i++) {
if (selectObject.options[i].selected) {
numberSelected++;
}
}
return numberSelected;
}
var btn = document.getElementById('btn');
btn.addEventListener('click', function() {
alert('Number of options selected: ' + howMany(document.selectForm.musicTypes));
});
</script>
Lệnh do...while
Lệnh do...while
thực hiện liên tục cho tới khi điều kiện xác định trả về false. Lệnh do...while
có dạng như sau:
do lệnh while (điều_kiện);
lệnh
luôn được thực thi một lần trước khi kiểm tra điều kiện (và rồi cứ thế cho tới khi điều kiện trả về false). Để thực thi nhiều lệnh, dùng khối lệnh ({ ... }
) để gom nhóm các câu lệnh. Nếu điều_kiện
trả về true, lệnh lại được thực thi một lần nữa. Sau mỗi lần thực thi, chương trình kiểm tra lại điều kiện. Khi điều kiện trả về false, chương trình dừng thực thi vòng lặp và truyền điều khiển xuống lệnh liền sau vòng do...while
.
Ví dụ
Trong ví dụ sau, lặp do
lặp ít nhất một lần và tái duyệt cho tới khi i
không nhỏ hơn 5.
var i = 0;
do {
i += 1;
console.log(i);
} while (i < 5);
Lệnh while
Lệnh while
thực thi các lệnh bên trong nó ngay khi điều kiện xác định trả về true. Lệnh while
có dạng như sau:
while (điều_kiện) lệnh
Nếu điều kiện trả về false, chương trình sẽ ngừng thực thi lệnh
bên trong vòng lặp và truyền điều khiển xuống lệnh liền sau vòng lặp.
Chương trình kiểm tra điều kiện trước khi thực thi lệnh
bên trong. Nếu điều kiện trả về true, lệnh
sẽ được thực thi và kiểm tra lại điều kiện. Nếu điều kiện trả về false, ngừng thực thi và truyền điều khiển xuống lệnh liền sau vòng lặp while
.
Để thực thi nhiều lệnh, dùng khối lệnh ({ ... }) để gom nhóm các câu lệnh.
Ví dụ 1
Vòng while
lặp lại cho tới khi n
nhỏ hơn 3:
var n = 0;
var x = 0;
while (n < 3) {
n++;
x += n;
}
Ứng với mỗi lần lặp, tăng n
thêm một và cộng giá trị đó vào x
. Bởi vậy, x
và n
có giá trị như sau:
- Sau lần lặp thứ nhất:
n
= 1 vàx
= 1 - Sau lần lặp thứ hai:
n
= 2 vàx
= 3 - Sau lần lặp thứ ba:
n
= 3 vàx
= 6
Sau khi hoàn thành lần lặp thứ ba, điều kiện n < 3
không còn trả về true nữa nên vòng lặp bị kết thúc.
Ví dụ 2
Hãy tránh lặp vô hạn. Hãy đảm bảo rằng điều kiện của vòng lặp sẽ dần trả về false; bằng không, vòng lặp sẽ không bao giờ kết thúc. Lệnh trong vòng lặp while
dưới đây được thực thi mãi mãi vì điều kiện không bao giờ trả về false:
while (true) {
console.log('Hello, world!');
}
Lệnh gán nhãn
label
tạo ra một lệnh đi kèm với một định danh, thông qua định danh giúp bạn tham chiếu tới nó từ những nơi khác trong chương trình của bạn. Chẳng hạn, bạn có thể dùng nhãn để định danh một vòng lặp, rồi dùng lệnh break
hoặc continue
để chương trình xác định có nên dừng hay tiếp tục thực thi vòng lặp hay không.
Cú pháp của lệnh gán nhãn có dạng như sau:
nhãn : lệnh
Giá trị của nhãn
có thể là định danh JavaScript bất kỳ nhưng không phải từ dành riêng (tên biến, tên hàm hoặc nhãn khác). lệnh
được gán với nhãn có thể là bất kỳ lệnh nào.
Ví dụ
Trong ví dụ này, nhãn markLoop
giúp định danh cho một vòng lặp while
.
markLoop:
while (theMark == true) {
doSomething();
}
Lệnh break
Dùng lệnh break
để kết thúc vòng lặp, kết thúc switch
, hoặc liên hợp với một lệnh được gán nhãn.
- Khi dùng
break
không kèm với nhãn, chương trình kết thúc ngay tức thì vòngwhile
,do-while
,for
, hoặcswitch
trong cùng bọc lệnhbreak
và truyền điều khiển xuống lệnh liền sau. - Khi dùng
break
kèm với nhãn, nó sẽ chấm dứt việc thực thi lệnh được gắn nhãn đó.
Cú pháp lệnh break
có dạng như sau:
break; break [nhãn];
Kiểu cú pháp đầu tiên kết thúc vòng lặp trong cục bao bọc hoặc switch
; kiểu thứ hai kết thúc lệnh gắn với nhãn.
Ví dụ 1
Trong ví dụ sau, lệnh lặp sẽ lặp qua từng phần tử của mảng (thông qua chỉ mục của từng phần tử) cho tới khi gặp phần tử có giá trị bằng theValue
:
for (var i = 0; i < a.length; i++) {
if (a[i] == theValue) {
break;
}
}
Ví dụ 2: Áp dụng break cho nhãn
var x = 0;
var z = 0;
labelCancelLoops: while (true) {
console.log('Outer loops: ' + x);
x += 1;
z = 1;
while (true) {
console.log('Inner loops: ' + z);
z += 1;
if (z === 10 && x === 10) {
break labelCancelLoops;
} else if (z === 10) {
break;
}
}
}
Lệnh continue
Lệnh continue
có thể dùng để tái duyệt các vòng while
, do-while
, for
, hoặc label
.
- Khi dùng
continue
không kèm theo label, chương trình ngừng thực thi lần lặp hiện tại của vòngwhile
,do-while
, hoặcfor
gần nhất bọc lệnhcontinue
và tiếp tục thực thi lần lặp tiếp theo. Trái với lệnhbreak
,continue
không dừng vòng lặp hoàn toàn. Trong vòng lặpwhile
, chương trình nhảy về đoạn xét điều kiện. Trong vọng lặpfor
, chương trình nhảy tớibiểu_thức_tăng_tiến
. - Khi dùng
continue
có kèm theo label, lệnhcontinue
sẽ áp dụng cho vòng lặp được gán nhãn đó.
Cú pháp của lệnh continue
có dạng như sau:
continue [label];
Ví dụ 1
Trong ví dụ sau, vòng while
với lệnh continue
thực thi khi giá trị của i
bằng 3. Thế nên, n
sẽ có giá trị là 1, 3, 7 và 12.
var i = 0;
var n = 0;
while (i < 5) {
i++;
if (i == 3) {
continue;
}
n += i;
console.log(n);
}
//1,3,7,12
var i = 0;
var n = 0;
while (i < 5) {
i++;
if (i == 3) {
// continue;
}
n += i;
console.log(n);
}
// 1,3,6,10,15
Ví dụ 2
Lệnh nhãn checkiandj
chứa nhãn checkj
. Nếu chương trình chạy tới continue
, chương trình sẽ ngừng thực hiện lần lặp hiện tại của checkj
và bắt đầu thực hiện lần lặp kế tiếp. Mỗi khi chạy tới continue
, checkj
tái duyệt cho tới khi biểu thức điều kiện của nó trả về false
. Khi false
được trả về, phần còn lại của lệnh checkiandj
được hoàn thành, và checkiandj
tái duyệt cho tới khi điều kiện của nó trả về false
. Khi false
được trả về, chương trình tiếp tục thực thi lệnh liền sau checkiandj
.
Nếu continue
gắn với nhãn checkiandj
, chương trình sẽ tiếp tục ở đầu lệnh checkiandj
.
var i = 0;
var j = 10;
checkiandj:
while (i < 4) {
console.log(i);
i += 1;
checkj:
while (j > 4) {
console.log(j);
j -= 1;
if ((j % 2) == 0) {
continue checkj;
}
console.log(j + ' is odd.');
}
console.log('i = ' + i);
console.log('j = ' + j);
}
Lệnh for...in
Lệnh for...in
lặp một biến (variable) đã được xác định trước, qua mọi thuộc tính có thể đếm được (enumerable properties) của đối tượng (object). Với từng phần tử riêng biệt, JavaScript thực thi các câu lệnh mà bạn định sẵn. Lệnh for...in
có dạng như sau:
for (variable in object) statement
Ví dụ
Hàm sau nhận vào tham số là một object và tên của object đó. Sau đó nó lặp qua mọi thuộc tính của object, với mỗi lần lặp nó trả về một chuỗi ký tự liệt kê các tên thuộc tính và giá trị của chúng.
function dump_props(obj, obj_name) {
var result = '';
for (var i in obj) {
result += obj_name + '.' + i + ' = ' + obj[i] + '<br>';
}
result += '<hr>';
return result;
}
Chẳng hạn với object car
có thuộc tính là make
và model
, result
sẽ là:
car.make = Ford
car.model = Mustang
Mảng
Mặc dù có thể dùng cách này để lặp qua từng phần tử của mảng Array
, lệnh for...in
sẽ trả về tên của thuộc tính mà người dùng tự định nghĩa kèm theo chỉ mục của mảng.
Bởi vậy, tốt hơn hết hãy sử dụng cách truyền thống là dùng vòng lặp for
với chỉ mục dạng số để lặp qua từng phần tử của mảng, bởi lệnh for...in
còn lặp qua cả thuộc tính mà người dùng tự định nghĩa (chẳng hạn như khi thêm một thuộc tính vào mảng, sẽ có ví dụ ở phía dưới).
for...of
statement
Lệnh for...of
tạo ra một vòng lặp, áp dụng với các đối tượng khả duyệt (iterable object) (bao gồm Array
, Map
, Set
, arguments
object, v.v...), và gọi lên một hook lặp tùy chỉnh (custom iteration hook) với các câu lệnh sẽ được thực thi cho giá trị của từng thuộc tính.
for (variable of object) statement
Ví dụ sau chỉ ra sự khác biệt giữa hai vòng lặp: for...of
và for...in
. Trong khi for...in
lặp qua tên thuộc tính, for...of
lặp qua giá trị thuộc tính:
var arr = [3, 5, 7];
arr.foo = 'hello';
for (var i in arr) {
console.log(i); // logs "0", "1", "2", "foo"
}
for (var i of arr) {
console.log(i); // logs 3, 5, 7
}