Чем отличаются var, let и const
Коротко: в новом коде пишите const, а let — если значение будет меняться. var — старый способ, от которого let и const отличаются в лучшую сторону.
var | let | const | |
|---|---|---|---|
| Видна внутри | всей функции | блока { … } | блока { … } |
| Обращение до объявления | undefined | ошибка | ошибка |
| Объявить второй раз | можно | ошибка | ошибка |
| Присвоить новое значение | можно | можно | ошибка |
Область видимости
let и const живут только в блоке — между фигурными скобками if, цикла, функции. var блок не замечает и видна во всей функции (или во всей программе, если объявлена вне функций):
if (true) {
var a = 1;
let b = 2;
}
console.log(a);
console.log(typeof b);1
undefineda «вытекла» из блока, b за его пределами не существует (typeof для необъявленного имени даёт "undefined", а прямое обращение console.log(b) выдало бы ошибку b is not defined).
Обращение до объявления
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 запрещает только записать в переменную другое значение. Содержимое объекта или массива менять можно:
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 в цикле
Классическая задача с собеседований:
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.