let
Оператор let
оголошує локальну змінну блочної області видимості, з необов'язковим присвоєнням їй початкового значення.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
Синтаксис
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN];
Параметри
var1
,var2
, …,varN
- Імена змінної або змінних, що оголошуються. Кожне ім'я має бути дозволеним ідентифікатором JavaScript.
value1
,value2
, …,valueN
Optional- Для кожної оголошеної змінної ви можете вказати її початкове значення будь-яким дозволеним виразом JavaScript.
Опис
Оператор let
дозволяє оголошувати змінні, що обмежені областю видимості блоку
або виразу, для якого використовуються, на відміну від ключового слова var
, яке визначає змінну глобально, чи локально для всієї функції, незалежно від області видимості блоку. Інша відмінність між операторами var
та let
полягає в тому, що останній ініціалізується тільки після оцінювання синтаксичним аналізатором (дивіться нижче).
Як і const
, let
не створює властивостей об'єкта window
при глобальному оголошенні (у області видимості верхнього рівня).
Пояснення, чому була обрана назва "let" можна подивитись тут.
Правила області видимості
Областю видимості змінних, оголошених через let
, є блок, у якому вони визначені, а також будь-які вкладені в нього блоки. У цьому сенсі let
дуже схожий на var
. Головна відмінність полягає в тому, що областю видимості змінної var
є уся замикаюча функція:
function varTest() {
var x = 1;
{
var x = 2; // та сама змінна!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // інша змінна
console.log(x); // 2
}
console.log(x); // 1
}
На верхньому рівні програм та функцій let
, на відміну від var
, не створює властивості глобального об'єкта. Наприклад:
var x = 'глобальна';
let y = 'глобальна';
console.log(this.x); // "глобальна"
console.log(this.y); // undefined
Імітація приватних членів
Працюючи з конструкторами (en-US), можна використовувати let
-зв'язування для створення приватних членів без використання замикань:
var Thing;
{
let privateScope = new WeakMap();
let counter = 0;
Thing = function() {
this.someProperty = 'foo';
privateScope.set(this, {
hidden: ++counter,
});
};
Thing.prototype.showPublic = function() {
return this.someProperty;
};
Thing.prototype.showPrivate = function() {
return privateScope.get(this).hidden;
};
}
console.log(typeof privateScope);
// "undefined"
var thing = new Thing();
console.log(thing);
// Thing {someProperty: "foo"}
thing.showPublic();
// "foo"
thing.showPrivate();
// 1
Такий самий шаблон приватності з використанням замикань для локальних змінних можна створити через var
, але це потребує функціональної області видимості (зазвичай, це НВФВ у шаблоні модуль) замість просто блочної області видимості у вищенаведеному прикладі.
Повторні оголошення
Повторне оголошення тієї самої змінної у області видимості тієї самої функції чи блоку спричиняє помилку SyntaxError
.
if (x) {
let foo;
let foo; // викидається SyntaxError.
}
Ви можете стикнутися з помилками у конструкціях switch (en-US), бо вони мають лише один блок.
let x = 1;
switch(x) {
case 0:
let foo;
break;
case 1:
let foo; // SyntaxError через повторне оголошення.
break;
}
Однак, важливо зазначити, що блок, вкладений у блок case, створить нове лексичне середовище блочної області видимості, яке не викличе помилок повторного оголошення, показаних вище.
let x = 1;
switch(x) {
case 0: {
let foo;
break;
}
case 1: {
let foo;
break;
}
}
Тимчасова мертва зона
На відміну від змінних, оголошених через var
, які спочатку мають значення undefined
, let
-змінні не ініціалізуються, поки не відбудеться обчислення їхнього оголошення. Звернення до змінної до ініціалізації призводить до викидання ReferenceError
. Змінна знаходиться у "тимчасовій мертвій зоні" від початку блоку і до проходження ініціалізації.
function do_something() {
console.log(bar); // undefined
console.log(foo); // ReferenceError
var bar = 1;
let foo = 2;
}
Тимчасова мертва зона та typeof
На відміну від просто неоголошених змінних та змінних, що містять значення undefined
, використання оператора typeof
для перевірки типу змінної, що знаходиться у своїй ТМЗ, викине ReferenceError
:
// виведе 'undefined'
console.log(typeof undeclaredVariable);
// призведе до 'ReferenceError'
console.log(typeof i);
let i = 10;
Ще один приклад тимчасової мертвої зони у поєднанні з лексичною областю видимості
Через наявність лексичної області видимості, ідентифікатор foo
у виразі (foo + 55)
оцінюється як ідентифікатор foo блоку if, а не розташована вище змінна foo зі значенням 33.
У цьому конретному рядку змінна foo
блоку if вже була створена у лексичному середовищі, але ще не пройшла (і перервала) свою ініціалізацію (яка є частиною інструкції).
Змінна foo
блоку if досі у тимчасовій мертвій зоні.
function test(){
var foo = 33;
if (true) {
let foo = (foo + 55); // ReferenceError
}
}
test();
Цей феномен може заплутати, наприклад, у наступній ситуації. Інструкція let n of n.a
вже знаходиться всередині приватної області видимості блоку циклу for. Отже, ідентифікатор n.a
вважається властивістю 'a' об'єкта 'n', розташованого у першій частині цієї ж інструкції ("let n").
Він досі знаходиться у тимчасовій мертвій зоні, оскільки його оголошення ще не було виконано та перервалось.
function go(n) {
// n тут визначений!
console.log(n); // Object {a: [1,2,3]}
for (let n of n.a) { // ReferenceError
console.log(n);
}
}
go({a: [1, 2, 3]});
Інші ситуації
При використанні всередині блоку, let
обмежує область видимості змінної цим блоком. Зауважте відмінність від var
, чия область видимості - функція, де відбулось оголошення.
var a = 1;
var b = 2;
if (a === 1) {
var a = 11; // глобальна область видимості
let b = 22; // областю видимості є блок if
console.log(a); // 11
console.log(b); // 22
}
console.log(a); // 11
console.log(b); // 2
Однак, комбінація оголошень var
та let
, наведена нижче, спричинить SyntaxError
через підняття var
наверх блоку. Це призводить до неявного повторного оголошення змінної.
let x = 1;
{
var x = 2; // SyntaxError через повторне оголошення
}
Специфікації
Специфікація | Статус | Коментар |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Let and Const Declarations' in that specification. |
Standard | Початкове визначення. Не визначає let-вирази та let-блоки. |
ECMAScript (ECMA-262) The definition of 'Let and Const Declarations' in that specification. |
Living Standard |
Сумісність з веб-переглядачами
BCD tables only load in the browser