Back

Объявление переменных в JavaScript: разбираемся с var, let и const

Объявление переменных в JavaScript: разбираемся с var, let и const

Современная разработка на JavaScript требует ясности в объявлении переменных JavaScript — однако многие разработчики до сих пор испытывают трудности с выбором между var, let и const. Понимание области видимости переменных ES6 — это не просто заучивание правил; это написание кода, который передаёт намерения и предотвращает ошибки до их возникновения.

Ключевые моменты

  • Блочная область видимости (let/const) обеспечивает лучшую изоляцию переменных, чем функциональная область видимости (var)
  • Временная мёртвая зона (Temporal Dead Zone) предотвращает использование переменных до их инициализации
  • const предотвращает переприсваивание, но не мутацию объектов и массивов
  • Современный JavaScript отдаёт предпочтение const по умолчанию, let при необходимости и избегает var

Понимание трёх ключевых слов объявления в JavaScript

JavaScript предлагает три способа объявления переменных, каждый из которых имеет свои особенности в отношении области видимости, поднятия (hoisting) и переприсваивания. Ваш выбор сигнализирует о разных намерениях как движку JavaScript, так и другим разработчикам, читающим ваш код.

Блочная область видимости против функциональной

Фундаментальное различие между современной областью видимости переменных ES6 и устаревшими паттернами заключается в том, как изолируются переменные:

function processData() {
    if (true) {
        var x = 1;  // Function-scoped
        let y = 2;  // Block-scoped
        const z = 3; // Block-scoped
    }
    console.log(x); // 1 (accessible)
    console.log(y); // ReferenceError
    console.log(z); // ReferenceError
}

С var переменные «вытекают» из блоков, но остаются внутри функций. И let, и const соблюдают границы блоков — любые фигурные скобки создают новую область видимости, включая те, что в циклах, условных конструкциях и обычных блоках.

Временная мёртвая зона: подробное объяснение

Объявления переменных JavaScript с let и const поднимаются (hoisted), но остаются неинициализированными до достижения их объявления. Это создаёт временную мёртвую зону (Temporal Dead Zone, TDZ):

console.log(myVar);   // undefined (hoisted, initialized)
console.log(myLet);   // ReferenceError (TDZ)
console.log(myConst); // ReferenceError (TDZ)

var myVar = 1;
let myLet = 2;
const myConst = 3;

TDZ предотвращает тонкие ошибки, которые часто вызывало поведение var. Вы не можете случайно использовать переменную до её правильной инициализации — движок немедленно выбросит ошибку.

Переприсваивание против мутации

Критическое различие, которое упускают многие разработчики: const предотвращает переприсваивание, а не мутацию:

const user = { name: 'Alice' };
user.name = 'Bob';          // Allowed (mutation)
user = { name: 'Charlie' }; // TypeError (reassignment)

const scores = [95, 87];
scores.push(91);            // Allowed
scores = [100, 100];        // TypeError

Для истинной неизменяемости комбинируйте const с Object.freeze() или библиотеками для работы с неизменяемыми данными. Само по себе ключевое слово объявления не делает ваши данные неизменяемыми — оно делает неизменяемой привязку (binding).

Современные лучшие практики объявления переменных

Кодовые базы JavaScript сегодня следуют чёткой иерархии:

  1. По умолчанию используйте const: применяйте для значений, которые не будут переприсваиваться. Это включает большинство переменных, даже объекты и массивы, которые вы будете мутировать.

  2. Используйте let для переприсваивания: счётчики циклов, переменные-аккумуляторы и значения, которые действительно требуют повторной привязки.

  3. Избегайте var в новом коде: не существует современного сценария использования, где var предоставляет преимущества перед let.

Современные инструменты обеспечивают соблюдение этих паттернов. Правила ESLint no-var и prefer-const автоматически отлавливают нарушения. TypeScript рассматривает правила области видимости переменных ES6 как фундаментальные, делая блочную область видимости ментальной моделью по умолчанию.

Особенности фреймворков

React-хуки зависят от предсказуемого поведения объявлений переменных JavaScript:

function Counter() {
    const [count, setCount] = useState(0); // const for the binding
    
    // Wrong: Can't reassign
    // count = count + 1;
    
    // Right: Use the setter
    setCount(count + 1);
}

Composition API во Vue и другие современные фреймворки следуют аналогичным паттернам, где доминирует const, потому что системы реактивности обрабатывают обновления через методы, а не через переприсваивание.

Почему устаревший код всё ещё использует var

Вы встретите var в старых кодовых базах по историческим причинам. До ES6 (2015) это был единственный вариант. Миграция требует тщательного тестирования, потому что:

  • Изменение var на let в циклах может исправить ошибки или внести их, в зависимости от поведения замыканий
  • Некоторый устаревший код намеренно эксплуатирует поднятие с функциональной областью видимости var
  • Старые инструменты сборки могут некорректно транспилировать область видимости переменных ES6

При рефакторинге используйте автоматизированные инструменты, такие как jscodeshift, с тщательным покрытием тестами. Не конвертируйте вручную тысячи объявлений — позвольте инструментам обработать механические изменения, пока вы проверяете поведение.

Заключение

Объявления переменных JavaScript в современном коде следуют простому правилу: используйте const по умолчанию, let когда нужно переприсваивание, и никогда var. Это не о следовании трендам — это о написании кода, который чётко выражает намерения и использует область видимости переменных ES6 для предотвращения целых категорий ошибок. Временная мёртвая зона, блочная область видимости и правила переприсваивания — это не препятствия, а ограждения, которые направляют вас к более поддерживаемому JavaScript.

Часто задаваемые вопросы

Да, const предотвращает только переприсваивание самой переменной, а не изменение содержимого. Вы можете добавлять, удалять или изменять свойства в объектах и элементы в массивах, объявленных с const. Переменная всегда указывает на один и тот же объект или массив в памяти.

Вы получите ReferenceError из-за временной мёртвой зоны. В отличие от var, которая возвращает undefined при обращении до объявления, переменные let и const существуют в неинициализированном состоянии до тех пор, пока код не достигнет строки их объявления.

Только при тщательном тестировании. Хотя это обычно полезно, изменение var на let в циклах может изменить поведение замыканий. Используйте автоматизированные инструменты рефакторинга с комплексным покрытием тестами, а не ручные изменения, чтобы избежать внесения ошибок.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay