В чем разница между let и var в JavaScript?
Основные различия между let и var
Ключевая разница между let и var заключается в области видимости (scope) и всплытии (hoisting). Давайте разберем каждый аспект подробно.
1. Область видимости (Scope)
var имеет функциональную область видимости — переменная видна во всей функции, независимо от того, в каком блоке она объявлена. let (и const) имеет блочную область видимости — переменная видна только внутри блока {}, где объявлена.
function example() {
if (true) {
var a = 1;
let b = 2;
}
console.log(a); // 1 — var "вылезает" за блок if
console.log(b); // ReferenceError — let живет только внутри if
}
// Другой пример с блоками:
{
var c = 3;
let d = 4;
}
console.log(c); // 3
console.log(d); // ReferenceError
2. Всплытие (Hoisting)
Обе конструкции "всплывают" (hoisting), но по-разному:
- var: объявление всплывает, инициализируется как
undefined— можно использовать до объявления - let: объявление всплывает, но НЕ инициализируется — находится во "временной мертвой зоне" (Temporal Dead Zone, TDZ) до строки объявления
console.log(x); // undefined — var всплыл и инициализирован
var x = 5;
console.log(y); // ReferenceError — let в TDZ
let y = 10;
3. Повторное объявление
var позволяет переобъявлять одну и ту же переменную, let — нет (в той же области видимости):
var a = 1;
var a = 2; // OK — переопределили
let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared
4. Проблема с циклами и setTimeout (ваш второй пример)
Это классическая проблема замыканий (closures). Объясним на примере:
// С var:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Вывод: 3, 3, 3
// Почему? var i имеет функциональную область видимости.
// К моменту выполнения setTimeout, цикл уже закончился и i = 3.
// Все три колбэка ссылаются на одну и ту же переменную i.
// С let:
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100);
}
// Вывод: 0, 1, 2
// Почему? let создает новую переменную j для каждой итерации цикла.
// Каждый колбэк "запоминает" свое значение j.
5. Глобальная область видимости
На глобальном уровне var создает свойство объекта window (в браузере), а let — нет:
var globalVar = 'я видна в window';
let globalLet = 'я не видна в window';
console.log(window.globalVar); // 'я видна в window'
console.log(window.globalLet); // undefined
Практические рекомендации
- Всегда используйте
let(илиconst) вместоvarв современном JavaScript const— для переменных, которые не должны переназначаться (по умолчанию)let— когда нужно переопределить переменнуюvar— избегайте, если только не поддерживаете очень старые браузеры (IE10 и ниже)
Запомните простое правило: let — это современная, безопасная замена var, которая ведет себя более предсказуемо и соответствует ожиданиям большинства разработчиков.
<<Дополнительный взгляд: let vs var через призму best practices
Коллеги уже подробно описали технические различия. Я хочу добавить практическую перспективу: почему сообщество JavaScript перешло на let/const.
Проблемы с var исторически приводили к трудноуловимым багам. Например:
// Классическая ошибка с var в циклах
var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
console.log('Нажата кнопка ' + i); // Всегда выводит последнее значение i
};
}
// Исправление с let
for (let i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
console.log('Нажата кнопка ' + i); // Каждая кнопка выводит свой номер
};
}
Еще один важный момент — читаемость кода. Когда вы видите let или const, вы сразу знаете границы жизни переменной. var же может "вылезти" из любого блока, что усложняет понимание кода.
Современные линтеры (ESLint) и TypeScript по умолчанию запрещают var в новых проектах. Это не просто мода — это осознанный выбор в пользу более безопасного и предсказуемого кода.
Мой совет: забудьте про var, используйте const по умолчанию, let — когда нужно переназначение. Ваш код станет чище, а багов — меньше.
Ответов пока нет.
Войдите чтобы оставить ответ