Разница в области действия переменных, объявленных с каждой.
На практике существует ряд полезных последствий разницы в области применения:
let
переменные видны только в их ближайшем включающем блоке ({ ... }
).
let
переменные можно использовать только в строках кода, которые появляются после объявления переменной (даже если они подняты !).
let
переменные не могут быть повторно объявлены последующими var
или let
.
- Глобальные
let
переменные не добавляются в глобальный window
объект.
let
переменные просты в использовании с замыканиями (они не вызывают условия гонки ).
Ограничения, налагаемые let
, уменьшают видимость переменных и увеличивают вероятность того, что неожиданные конфликты имен будут обнаружены на ранней стадии. Это облегчает отслеживание и рассуждение о переменных, включая их достижимость (помогая восстановить неиспользуемую память).
Следовательно, let
переменные с меньшей вероятностью будут вызывать проблемы при использовании в больших программах или когда независимо разработанные структуры объединяются новыми и неожиданными способами.
var
все еще может быть полезным, если вы уверены, что хотите использовать эффект одинарной привязки при использовании замыкания в цикле (# 5) или для объявления внешне видимых глобальных переменных в вашем коде (# 4). Использование var
для экспорта может быть заменено, если export
мигрирует из пространства транспортера в основной язык.
Примеры
1. Не использовать вне ближайшего ограждающего блока:
Этот блок кода будет выдавать ошибку ссылки, потому что второе использование x
происходит за пределами блока, где оно объявлено с let
:
{
let x = 1;
}
console.log(`x is ${x}`); // ReferenceError during parsing: "x is not defined".
Напротив, работает тот же пример с var
.
2. Не использовать до объявления:
Этот блок кода выдаст ReferenceError
до того, как код может быть запущен, потому что x
используется до его объявления:
{
x = x + 1; // ReferenceError during parsing: "x is not defined".
let x;
console.log(`x is ${x}`); // Never runs.
}
Напротив, тот же самый пример с var
анализирует и запускает без каких-либо исключений.
3. Без объявления:
Следующий код демонстрирует, что переменная, объявленная с let
, не может быть повторно объявлена позже:
let x = 1;
let x = 2; // SyntaxError: Identifier 'x' has already been declared
4. Глобалы, не привязанные к window
:
var button = "I cause accidents because my name is too common.";
let link = "Though my name is common, I am harder to access from other JS files.";
console.log(link); // OK
console.log(window.link); // undefined (GOOD!)
console.log(window.button); // OK
5. Простота использования с крышками:
Переменные, объявленные с var
, плохо работают с замыканиями внутри циклов. Вот простой цикл, который выводит последовательность значений, которые переменная i
имеет в разные моменты времени:
for (let i = 0; i < 5; i++) {
console.log(`i is ${i}`), 125/*ms*/);
}
В частности, это выводит:
i is 0
i is 1
i is 2
i is 3
i is 4
В JavaScript мы часто используем переменные значительно позже, чем при их создании. Когда мы продемонстрируем это путем задержки вывода с закрытием, переданным в setTimeout
:
for (let i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
... вывод остается неизменным, пока мы придерживаемся let
. Напротив, если бы мы использовали var i
вместо:
for (var i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
... цикл неожиданно выдает «i is 5» пять раз:
i is 5
i is 5
i is 5
i is 5
i is 5