Перейти к содержимому

11. var vs let vs const — hoisting и TDZ

Иллюстрация к уроку Привет, будущие повелители JavaScript! Сегодня мы разберемся с тремя ключевыми способами объявления переменных: var, let и const. Поймем, чем они отличаются и как их поведение влияет на работу нашего кода, особенно в контексте hoisting и Temporal Dead Zone (TDZ).

В JavaScript для объявления переменных используются var, let и const. Выбор между ними влияет на область видимости переменной и возможность её изменения.

  • var: Объявляет переменную, область видимости которой ограничена функцией (function scope) или, если объявлена вне функции, – глобальной областью видимости.
  • let: Объявляет переменную, область видимости которой ограничена блоком (block scope) – это означает, что она видна только внутри блока {} в котором объявлена.
  • const: Объявляет константу, значение которой нельзя изменить после инициализации. Область видимости также ограничена блоком (block scope).
function exampleVar() {
var x = 10;
if (true) {
var x = 20; // Перезаписывает внешнюю переменную x
console.log(x); // Выведет 20
}
console.log(x); // Выведет 20
}
exampleVar();
function exampleLetConst() {
let y = 10;
if (true) {
let y = 20; // Создает новую переменную y в этом блоке
console.log(y); // Выведет 20
const z = 30;
// z = 40; // Вызовет ошибку, так как const нельзя переназначить
}
console.log(y); // Выведет 10
// console.log(z); // Вызовет ошибку, z не определена за пределами блока
}
exampleLetConst();

Hoisting (поднятие) – это механизм в JavaScript, при котором объявления переменных и функций перемещаются в начало их области видимости до начала выполнения кода. Важно понимать, что поднимается только объявление, а не инициализация (присвоение значения).

  • var: Переменные, объявленные с помощью var, поднимаются и инициализируются значением undefined. Это означает, что можно использовать переменную до её объявления, но она будет иметь значение undefined.
  • let и const: Переменные, объявленные с помощью let и const, также поднимаются, но не инициализируются. Это означает, что попытка обратиться к переменной до её объявления вызовет ошибку ReferenceError: Cannot access 'variable' before initialization. Это состояние называется Temporal Dead Zone (TDZ).
console.log(myVar); // Выведет undefined
var myVar = 5;
// console.log(myLet); // Вызовет ReferenceError: Cannot access 'myLet' before initialization
let myLet = 10;
// console.log(myConst); // Вызовет ReferenceError: Cannot access 'myConst' before initialization
const myConst = 15;

TDZ – это временная “мертвая зона”, в которой переменная, объявленная с помощью let или const, существует, но к ней нельзя обратиться до момента её объявления в коде. Попытка доступа к переменной в TDZ приводит к ошибке ReferenceError.

function tdzExample() {
console.log(myVar); // undefined
// console.log(myLet); // ReferenceError: Cannot access 'myLet' before initialization
var myVar = "var variable";
let myLet = "let variable";
}
tdzExample();

В современных JavaScript-фреймворках, таких как React, Angular и Vue, let и const используются повсеместно. Например, при работе с React компонентами, const часто используется для объявления неизменяемых переменных, содержащих props или state, а let используется для переменных, которые могут меняться в пределах компонента. Использование let и const позволяет избежать случайных ошибок, связанных с переопределением переменных, и делает код более предсказуемым.

// Пример React компонента
function MyComponent(props) {
const name = props.name; // Использование const для props
let count = 0; // Использование let для state (упрощенный пример)
function handleClick() {
count++; // Изменяем значение count
console.log(`Clicked ${count} times`);
}
return (
<button onClick={handleClick}>
Hello, {name}! Click me.
</button>
);
}
  • var имеет function scope, let и const имеют block scope.
  • var поднимается и инициализируется undefined, let и const поднимаются, но не инициализируются (TDZ).
  • const используется для констант, let для переменных, которые могут изменяться.
  • В современном JavaScript рекомендуется использовать let и const вместо var для повышения предсказуемости и избежания ошибок.
  • TDZ помогает выявлять ошибки до того, как они приведут к неожиданному поведению программы.