var vs let
У объявлений переменной через let есть три основных отличия от var:
Область видимости переменной
let– блок{...}.Как мы помним, переменная, объявленная через
var, видна везде в функции.Переменная, объявленная через
let, видна только в рамках блока{...}, в котором объявлена.Это, в частности, влияет на объявления внутри
if,whileилиfor.Например, переменная через
var:var apples = 5; if (true) { var apples = 10; alert(apples); // 10 (внутри блока) } alert(apples); // 10 (снаружи блока то же самое)В примере выше
apples– одна переменная на весь код, которая модифицируется вif.То же самое с
letбудет работать по-другому:let apples = 5; // (*) if (true) { let apples = 10; alert(apples); // 10 (внутри блока) } alert(apples); // 5 (снаружи блока значение не изменилось)Здесь, фактически, две независимые переменные
apples, одна – глобальная, вторая – в блокеif.Заметим, что если объявление
let applesв первой строке(*)удалить, то в последнемalertбудет ошибка: переменная не определена:if (true) { let apples = 10; alert(apples); // 10 (внутри блока) } alert(apples); // ошибка!Это потому что переменная
letвсегда видна именно в том блоке, где объявлена, и не более.Переменная
letвидна только после объявления.Как мы помним, переменные
varсуществуют и до объявления. Они равныundefined:alert(a); // undefined var a = 5;С переменными
letвсё проще. До объявления их вообще нет.Такой доступ приведёт к ошибке:
alert(a); // ошибка, нет такой переменной let a = 5;Заметим также, что переменные
letнельзя повторно объявлять. То есть, такой код выведет ошибку:let x; let x; // ошибка: переменная x уже объявленаЭто – хоть и выглядит ограничением по сравнению с
var, но на самом деле проблем не создаёт. Например, два таких цикла совсем не конфликтуют:// каждый цикл имеет свою переменную i for(let i = 0; i<10; i++) { /* … */ } for(let i = 0; i<10; i++) { /* … */ } alert( i ); // ошибка: глобальной i нетПри объявлении внутри цикла переменная
iбудет видна только в блоке цикла. Она не видна снаружи, поэтому будет ошибка в последнемalert.При использовании в цикле, для каждой итерации создаётся своя переменная.
Переменная
var– одна на все итерации цикла и видна даже после цикла:for(var i=0; i<10; i++) { /* … */ } alert(i); // 10С переменной
let– всё по-другому.Каждому повторению цикла соответствует своя независимая переменная
let. Если внутри цикла есть вложенные объявления функций, то в замыкании каждой будет та переменная, которая была при соответствующей итерации.Это позволяет легко решить классическую проблему с замыканиями, описанную в задаче Армия функций.
function makeArmy() { let shooters = []; for (let i = 0; i < 10; i++) { shooters.push(function() { alert( i ); // выводит свой номер }); } return shooters; } var army = makeArmy(); army[0](); // 0 army[5](); // 5Если бы объявление было
var i, то была бы одна переменнаяiна всю функцию, и вызовы в последних строках выводили бы10.А выше объявление
let iсоздаёт для каждого повторения блока в цикле свою переменную, которую функция и получает из замыкания в последних строках.
Last updated