--- title: let slug: Web/JavaScript/Reference/Statements/let translation_of: Web/JavaScript/Reference/Statements/let ---
let
объявляет переменную с блочной областью видимости с возможностью инициализировать её значением.let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
var1
, var2
, …, varN
value1
, value2
, …, valueN
Директива let
позволяет объявить локальную переменную с областью видимости, ограниченной текущим блоком кода . В отличие от ключевого слова var
, которое объявляет переменную глобально или локально во всей функции, независимо от области блока.
Объяснение, почему было выбрано название "let" можно найти здесь.
Областью видимости переменных, объявленных ключевым словом let
, является блок, в котором они объявлены, и все его подблоки. В этом работа директива let
схожа с работой директивы var
. Основная разница заключается в том, что областью видимости переменной, объявленной директивой var
, является вся функция, в которой она объявлена:
function varTest() { var x = 1; if (true) { var x = 2; // та же переменная! console.log(x); // 2 } console.log(x); // 2 } function letTest() { let x = 1; if (true) { let x = 2; // другая переменная console.log(x); // 2 } console.log(x); // 1 }
let
иногда делает код чище при использовании вложенных функций.
var list = document.getElementById("list"); for (let i = 1; i <= 5; i++) { let item = document.createElement('li'); item.appendChild(document.createTextNode('Item ' + i)); item.onclick = function(ev) { console.log('Item ' + i + ' is clicked.'); }; list.appendChild(item); } // чтобы получить такой же эффект с использованием 'var' // необходимо создать новый контекст // используя замыкание, чтобы сохранить значение неизменённым for (var i = 1; i <= 5; i++) { var item = document.createElement("li"); item.appendChild(document.createTextNode("Item " + i)); (function(i){ item.onclick = function(ev) { console.log('Item ' + i + ' is clicked.'); }; })(i); list.appendChild(item); }
Пример выше будет выполнен как и ожидается, так как пять экземпляров внутренней функции (анонимной) будут ссылаться на пять разных экземпляров переменной i
. Пример будет выполнен неверно, если заменить директиву let
на var,
или удалить переменную i
из параметров вложенной функции и использовать внешнюю переменную i
во внутренней функции.
На верхнем уровне скриптов и функций let, в отличии от var, не создаёт свойства на глобальном объекте
. Например:
var x = 'global_x'; let y = 'global_y'; console.log(this.x); // 'global_x' console.log(this.y); // undefined
В выводе программы будет отображено слово "global_x" для this.x
, но undefined
для this.y
.
При взаимодействии с конструкторами можно использовать выражение let
чтобы открыть доступ к одному или нескольким приватным членам через использование замыканий:
var SomeConstructor; { let privateScope = {}; SomeConstructor = function SomeConstructor() { this.someProperty = 'foo'; privateScope.hiddenProperty = 'bar'; } SomeConstructor.prototype.showPublic = function() { console.log(this.someProperty); // foo } SomeConstructor.prototype.showPrivate = function() { console.log(privateScope.hiddenProperty); // bar } } var myInstance = new SomeConstructor(); myInstance.showPublic(); myInstance.showPrivate(); console.log(privateScope.hiddenProperty); // error
Эта техника позволяет получить только "статичное" приватное состояние - в примере выше, все экземпляры полученные из конструктора SomeConstructor
будут ссылаться на одну и ту же область видимости privateScope
.
let
Повторное объявление той же переменной в том же блоке или функции приведёт к выбросу исключения SyntaxError.
if (x) { let foo; let foo; // SyntaxError thrown. }
В стандарте ECMAScript 2015 переменные, объявленные директивой let, переносятся в начало блока. Но если вы сошлётесь в блоке на переменную, до того как она объявлена директивой let, то это приведёт к выбросу исключения ReferenceError
, потому что переменная находится во "временной мёртвой зоне" с начала блока и до места её объявления. (В отличии от переменной, объявленной через var
, которая просто будет содержать значение undefined
)
function do_something() {
console.log(bar); // undefined
console.log(foo); // ReferenceError: foo is not defined
var bar = 1;
let foo = 2;
}
Вы можете столкнуться с ошибкой в операторах блока switch
, так как он имеет только один подблок.
switch (x) { case 0: let foo; break; case 1: let foo; // Выброс SyntaxError из-за повторного объявления переменной break; }
Использование let в циклах
for
Вы можете использовать ключевое слово let
для привязки переменных к локальной области видимости цикла for
. Разница с использованием var
в заголовке цикла for
, заключается в том, что переменные объявленные var
, будут видны во всей функции, в которой находится этот цикл.
var i=0; for ( let i=i ; i < 10 ; i++ ) { console.log(i); }
for (let expr1; expr2; expr3) statement
В этом примере expr2, expr3, statement заключены в неявный блок, который содержит блок локальных переменных, объявленных конструкцией let expr1
. Пример приведён выше.
let
vs var
Когда let используется внутри блока, то область видимости переменной ограничивается этим блоком. Напомним, что отличие заключается в том, что областью видимости переменных, объявленных директивой var, является вся функция, в которой они были объявлены.
var a = 5; var b = 10; if (a === 5) { let a = 4; // The scope is inside the if-block var b = 1; // The scope is inside the function console.log(a); // 4 console.log(b); // 1 } console.log(a); // 5 console.log(b); // 1
let
в циклахВы можете использовать ключевое слово let
для привязки переменных к локальной области видимости цикла for
, вместо того что бы использовать глобальные переменные (объявленные с помощью var
).
for (let i = 0; i<10; i++) { console.log(i); // 0, 1, 2, 3, 4 ... 9 } console.log(i); // i is not defined
let
let
блокПоддержка let
блоков была убрана в Gecko 44 {{bug(1023609)}}.
let блок предоставляет способ, ассоциировать значения с переменными внутри области видимости этого блока, без влияния на значения переменных с теми же именами вне этого блока.
let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) block;
let
блок предоставляет локальную область видимости для переменных. Работа его заключается в привязке нуля или более переменных к области видимости этого блока кода, другими словами, он является блоком операторов. Отметим, что область видимости переменных, объявленных директивой var
, в блоке let
, будет той же самой, что и если бы эти переменные были объявлены вне блока let
, иными словами областью видимости таких переменных по-прежнему является функция. Скобки в блоке let
являются обязательными. Опускание их приведёт к синтаксической ошибке.
var x = 5; var y = 0; let (x = x+10, y = 12) { console.log(x+y); // 27 } console.log(x + y); // 5
Правила для этого блока кода аналогичны как и для любого другого блока кода в JavaScript. Он может содержать свои локальные переменные, объявленные let
.
Областью видимости переменных, объявленных директивой let
, в блоке let
является сам блок и все подблоки в нем, если они не содержат объявлений переменных с теми же именами.
let
выраженияПоддержка let выражений
была убрана в Gecko 41 {{bug(1023609)}}.
let выражение
позволяет объявить переменные с областью видимости ограниченной одним выражением.
let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) expression;
Вы можете использовать let для объявления переменных, областью видимости которых является только одно выражение:
var a = 5; let(a = 6) console.log(a); // 6 console.log(a); // 5
В данном let
выражении:
let (decls) expr
expr
оборачивается в неявный блок.
Specification | Status | Comment |
---|---|---|
{{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')}} |
{{CompatibilityTable}}
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support |
{{CompatChrome(41.0)}} |
{{ CompatGeckoDesktop("1.8.1") }} [1] | 11 | 17 | {{CompatUnknown}} |
Temporal dead zone | {{CompatUnknown}} | {{ CompatGeckoDesktop("35") }} [1] | {{CompatUnknown}} | {{CompatUnknown}} | {{CompatUnknown}} |
let expression {{non-standard_inline}} |
{{CompatNo}} | {{ CompatGeckoDesktop("1.8.1") }} [1] | {{CompatNo}} | {{CompatNo}} | {{CompatNo}} |
let block {{non-standard_inline}} |
{{CompatNo}} | {{ CompatGeckoDesktop("1.8.1") }} [1] | {{CompatNo}} | {{CompatNo}} | {{CompatNo}} |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | {{CompatUnknown}} |
{{CompatChrome(41.0)}} |
{{ CompatGeckoMobile("1.8.1") }} [1] | {{CompatUnknown}} | {{CompatUnknown}} | {{CompatUnknown}} |
Temporal dead zone | {{CompatUnknown}} | {{CompatUnknown}} | {{ CompatGeckoMobile("35") }} [1] | {{CompatUnknown}} | {{CompatUnknown}} | {{CompatUnknown}} |
let expression {{non-standard_inline}} |
{{CompatNo}} | {{CompatNo}} | {{ CompatGeckoMobile("1.8.1") }} [1] | {{CompatNo}} | {{CompatNo}} | {{CompatNo}} |
let block {{non-standard_inline}} |
{{CompatNo}} | {{CompatNo}} | {{ CompatGeckoMobile("1.8.1") }} [1] | {{CompatNo}} | {{CompatNo}} | {{CompatNo}} |
let
был доступен только для блоков кода обёрнутых в HTML <script type="application/javascript;version=1.7">
block (or higher version) и имел другую семантику.dom.workers.latestJSVersion
флагом ({{bug(487070)}}). Без версии let
, флаг будет удалён в будущем ({{bug(1219523)}}).let
в SpIderMonkey отслеживается в {{bug(950547)}}