Ответ 1
С var
у вас есть область функций, и только одна общая привязка для всех ваших итераций цикла - т.е. i
в каждом обратном вызове setTimeout означает тот же > , которая наконец равна 6 после окончания итерации цикла.
С let
у вас есть область блока и при использовании в цикле for
вы получаете новое привязку для каждой итерации, то есть i
в каждом обратном вызове setTimeout означает другая переменная, каждая из которых имеет другое значение: первая - 0, следующая - 1 и т.д.
Итак, это:
(function timer() {
for (let i = 0; i <= 5; i++) {
setTimeout(function clog() { console.log(i); }, i * 1000);
}
})();
эквивалентно этому, используя только var:
(function timer() {
for (var j = 0; j <= 5; j++) {
(function () {
var i = j;
setTimeout(function clog() { console.log(i); }, i * 1000);
}());
}
})();
используя сразу вызываемое выражение функции, чтобы использовать область действия функции аналогично тому, как область блока работает в примере с let
.
Его можно было бы написать короче, не используя имя j
, но, возможно, это было бы не так ясно:
(function timer() {
for (var i = 0; i <= 5; i++) {
(function (i) {
setTimeout(function clog() { console.log(i); }, i * 1000);
}(i));
}
})();
И еще короче со стрелками:
(() => {
for (var i = 0; i <= 5; i++) {
(i => setTimeout(() => console.log(i), i * 1000))(i);
}
})();
(Но если вы можете использовать функции стрелок, нет причин использовать var
.)
Вот как Babel.js переводит ваш пример с let
для работы в средах, где let
недоступен:
"use strict";
(function timer() {
var _loop = function (i) {
setTimeout(function clog() {
console.log(i);
}, i * 1000);
};
for (var i = 0; i <= 5; i++) {
_loop(i);
}
})();
Спасибо Майкл Гири за размещение ссылки на Babel.js в комментариях. См. Ссылку в комментарии для демонстрации в реальном времени, где вы можете изменить что-либо в коде и посмотреть, что перевод происходит сразу. Интересно посмотреть, как можно перевести и другие функции ES6.