Với var in ra 3 3 3. Với let in ra 0 1 2.
var có phạm vi function, nên cả ba callback đều capture cùng một biến i. Khi timer chạy (sau khi vòng lặp kết thúc), i đã là 3.
let có phạm vi block, và spec quy định mỗi vòng lặp tạo một binding mới rồi copy giá trị của vòng trước sang. Ba callback capture ba biến khác nhau.
js
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 3 3 3
for (let j = 0; j < 3; j++) setTimeout(() => console.log(j)); // 0 1 2Cách sửa khi buộc phải dùng var — tạo scope riêng bằng IIFE hoặc tham số:
js
for (var k = 0; k < 3; k++) {
(function (captured) {
setTimeout(() => console.log(captured));
})(k);
}Lỗi này hay xuất hiện thật khi gắn handler trong vòng lặp (buttons[i].onclick = () => open(items[i])) — mọi nút cùng mở phần tử cuối.