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 đóng gói (closure) trên 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 đóng gói trên 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.