--- title: let slug: Web/JavaScript/Reference/Statements/let tags: - ECMAScript 2015 - JavaScript - let - змінні translation_of: Web/JavaScript/Reference/Statements/let ---
Оператор let оголошує локальну змінну блочної області видимості, з необов'язковим присвоєнням їй початкового значення.
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN];
var1, var2, …, varNvalue1, value2, …, valueN {{optional_inline}}Оператор let дозволяє оголошувати змінні, що обмежені областю видимості {{jsxref("statements/block", "блоку")}} або виразу, для якого використовуються, на відміну від ключового слова {{jsxref("statements/var", "var")}}, яке визначає змінну глобально, чи локально для всієї функції, незалежно від області видимості блоку. Інша відмінність між операторами {{jsxref("statements/var", "var")}} та let полягає в тому, що останній ініціалізується тільки після оцінювання синтаксичним аналізатором (дивіться нижче).
Як і {{jsxref("statements/const", "const", "Description")}}, let не створює властивостей об'єкта {{domxref('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
Працюючи з конструкторами, можна використовувати 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, але це потребує функціональної області видимості (зазвичай, це НВФВ у шаблоні модуль) замість просто блочної області видимості у вищенаведеному прикладі.
Повторне оголошення тієї самої змінної у області видимості тієї самої функції чи блоку спричиняє помилку {{jsxref("SyntaxError")}}.
if (x) {
let foo;
let foo; // викидається SyntaxError.
}
Ви можете стикнутися з помилками у конструкціях switch, бо вони мають лише один блок.
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 через повторне оголошення
}
| Специфікація | Статус | Коментар |
|---|---|---|
| {{SpecName('ES2015', '#sec-let-and-const-declarations', 'Let and Const Declarations')}} | {{Spec2('ES2015')}} | Початкове визначення. Не визначає let-вирази та let-блоки. |
| {{SpecName('ESDraft', '#sec-let-and-const-declarations', 'Let and Const Declarations')}} | {{Spec2('ESDraft')}} |
{{Compat("javascript.statements.let")}}