Глиф Учебники

Чем отличаются var, let и const

Справочник · JavaScript · 1 минута чтения

Коротко: в новом коде пишите const, а let — если значение будет меняться. var — старый способ, от которого let и const отличаются в лучшую сторону.

varletconst
Видна внутривсей функцииблока { … }блока { … }
Обращение до объявленияundefinedошибкаошибка
Объявить второй разможноошибкаошибка
Присвоить новое значениеможноможноошибка

Область видимости

let и const живут только в блоке — между фигурными скобками if, цикла, функции. var блок не замечает и видна во всей функции (или во всей программе, если объявлена вне функций):

JavaScript
if (true) {
  var a = 1;
  let b = 2;
}

console.log(a);
console.log(typeof b);
Вывод
1
undefined

a «вытекла» из блока, b за его пределами не существует (typeof для необъявленного имени даёт "undefined", а прямое обращение console.log(b) выдало бы ошибку b is not defined).

Обращение до объявления

JavaScript
console.log(x);
var x = 5;

try {
  console.log(y);
  let y = 5;
} catch (err) {
  console.log(err.message);
}
Вывод
undefined
Cannot access 'y' before initialization

Объявление var движок как бы поднимает в начало функции (это называют всплытием, hoisting), но без значения — поэтому undefined вместо ошибки. Опечатки и неверный порядок кода так остаются незамеченными. let и const до строки объявления трогать нельзя — ошибка сразу показывает проблему.

Повторное объявление

var x = 1; var x = 2; — работает, вторая строка молча перезаписывает первую. С let или const такой код даже не запустится: SyntaxError: Identifier 'x' has already been declared. В длинном файле это спасает от случайного повторного использования имени.

const — не «неизменяемый объект»

const запрещает только записать в переменную другое значение. Содержимое объекта или массива менять можно:

JavaScript
const list = [1, 2];
list.push(3);
console.log(list);

try {
  list = [];
} catch (err) {
  console.log(err.message);
}
Вывод
[ 1, 2, 3 ]
Assignment to constant variable.

Ловушка var в цикле

Классическая задача с собеседований:

JavaScript
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log("var:", i), 0);
}

for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log("let:", j), 0);
}
Вывод
var: 3
var: 3
var: 3
let: 0
let: 1
let: 2

С var переменная i одна на весь цикл: к моменту, когда сработают таймеры, цикл закончился и i равна 3. С let на каждом шаге цикла создаётся своя j, и каждая функция запоминает своё значение.

Глобальные переменные в браузере

var вне функций в обычном скрипте становится свойством window: после var count = 1 появляется window.count, и переменная может столкнуться с одноимённым свойством браузера или другого скрипта. let и const свойств window не создают. Ещё одна причина не писать var.