let
Объем блока
Переменные, объявленные с использованием ключевого слова let
, имеют область видимости, то есть они доступны только в блоке , в котором они были объявлены.
На верхнем уровне (вне функции)
На верхнем уровне переменные, объявленные с использованием let
, не создают свойств для глобального объекта.
var globalVariable = 42;
let blockScopedVariable = 43;
console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43
console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined
Внутри функции
Внутри функции (но за пределами блока) let
имеет ту же область действия, что и var
.
(() => {
var functionScopedVariable = 42;
let blockScopedVariable = 43;
console.log(functionScopedVariable); // 42
console.log(blockScopedVariable); // 43
})();
console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
Внутри блока
Переменные, объявленные с использованием let
внутри блока, недоступны вне этого блока.
{
var globalVariable = 42;
let blockScopedVariable = 43;
console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43
}
console.log(globalVariable); // 42
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
Внутри петли
На переменные, объявленные в циклах let
, можно ссылаться только внутри этого цикла.
for (var i = 0; i < 3; i++) {
var j = i * 2;
}
console.log(i); // 3
console.log(j); // 4
for (let k = 0; k < 3; k++) {
let l = k * 2;
}
console.log(typeof k); // undefined
console.log(typeof l); // undefined
// Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.
Петли с пробками
Если вы используете let
вместо var
в цикле, с каждой итерацией вы получаете новую переменную. Это означает, что вы можете безопасно использовать замыкание внутри петли.
// Logs 3 thrice, not what we meant.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Logs 0, 1 and 2, as expected.
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 0);
}
Временная мертвая зона
Из-за временной мертвой зоны переменные, объявленные с использованием let
, не могут быть доступны до их объявления. Попытка сделать это выдает ошибку.
console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;
Без повторного объявления
Нельзя объявлять одну и ту же переменную несколько раз, используя let
. Вы также не можете объявить переменную, используя let
с тем же идентификатором, что и другая переменная, которая была объявлена с использованием var
.
var a;
var a; // Works fine.
let b;
let b; // SyntaxError: Identifier 'b' has already been declared
var c;
let c; // SyntaxError: Identifier 'c' has already been declared
const
const
очень похож на let
- это блок-область и имеет TDZ. Однако есть две разные вещи.
Нет переназначения
Переменная, объявленная с использованием const
, не может быть переназначена.
const a = 42;
a = 43; // TypeError: Assignment to constant variable.
Обратите внимание, что это не означает, что значение является неизменным. Его свойства все еще могут быть изменены.
const obj = {};
obj.a = 42;
console.log(obj.a); // 42
Если вы хотите иметь неизменный объект, вы должны использовать Object.freeze()
.
Требуется инициализатор
Вы всегда должны указывать значение при объявлении переменной, используя const
.
const a; // SyntaxError: Missing initializer in const declaration