Перевод статьи «Var, Let, and Const – What’s the Difference?».

С выходом ES2015 (ES6) мы получили много нового отличного функционала. С учетом того, что сейчас уже 2020 год, можно предположить, что большинство JavaScript-разработчиков со всеми новшествами уже ознакомились и начали их применять на практике.
Но может быть и так, что для некоторых программистов произошедшие изменения так и остались тайной за семью печатями.
Одним из важных новшеств ES6 было появление операторов let
и const
, используемых для объявления переменных. Но чем эти операторы отличаются от старого доброго var
, который мы использовали раньше? Если вы все еще не разобрались в этом, наша статья вам поможет.
В этой статье мы обсудим разницу между var
, let
и const
в разрезе их области видимости и поднятия.
Var
До наступления эпохи ES6 в объявлении переменных царил оператор var
. Но объявление переменных при помощи этого оператора приводило к некоторым проблемам. Именно поэтому возникла необходимость ввода в язык новых способов объявления переменных. Но прежде чем перейти к разбору проблем, давайте остановимся на применении оператора var
.
Область видимости переменных, объявленных при помощи var
Область видимости это часть программы, в которой будет доступна объявленная переменная. Переменные, объявленные при помощи var
, могут иметь как глобальную, так и локальную область видимости.
Мы говорим о глобальной области видимости, когда переменная объявлена вне функции. Это означает, что любая переменная, объявленная при помощи оператора var вне блока функции, будет доступна во всем window
.
Но если переменная объявляется при помощи var
внутри функции, она имеет локальную область видимости. Это означает, что доступ к ней есть только в рамках этой функции.
Чтобы разобраться, давайте рассмотрим пример.
var greeter = "hey hi"; function newFunction() { var hello = "hello"; }
В этом примере greeter
имеет глобальную область видимости, потому что существует вне функции. А вот область видимости hello
локальна. У нас нет доступа к переменной hello
вне функции, в которой она объявлена. Поэтому, если мы сделаем так, то получим ошибку:
var tester = "hey hi"; function newFunction() { var hello = "hello"; } console.log(hello); // error: hello is not defined
Мы получили ошибку, поскольку переменная hello
недоступна вне функции.
Переменные, объявленные при помощи var, могут как объявляться заново, так и обновляться
То есть, мы можем сделать вот так:
var greeter = "hey hi"; var greeter = "say Hello instead";
— и это не приведет к ошибке.
И вот так мы тоже не получим ошибок:
var greeter = "hey hi"; greeter = "say Hello instead";
Поднятие (hoisting) var
В JavaScript поднятие это механизм, обеспечивающий перемещение объявлений переменных и функций в верх их области видимости перед выполнением кода. Это означает, что если мы сделаем так:
console.log (greeter); var greeter = "say hello"
интерпретироваться это будет как:
var greeter; console.log(greeter); //greeter is undefined greeter = "say hello"
Таким образом, переменные, объявленные при помощи var
, поднимаются в верх своей области видимости и инициализируются присвоением какого-нибудь значения или undefined
.
Проблемы, возникающие при использовании var
Чтобы пояснить, в чем недостаток использования var
, обратимся к примеру.
var greeter = "hey hi"; var times = 4; if (times > 3) { var greeter = "say Hello instead"; } console.log(greeter) //"say Hello instead"
Поскольку times > 3
возвращает истину, переменная greeter объявляется повторно со значением "say Hello instead"
. Это не проблема, если вы знаете, что делаете, и действительно хотите заново объявить переменную greeter
. Но если вы не осознаете, что эта переменная уже объявлялась, вы столкнетесь с проблемами.
Если вы использовали greeter
в других частях вашего кода, вы можете быть удивлены результатами работы программы. Скорее всего, у вас появится много багов. Вот поэтому нам нужны let
и const
.
Let

Сейчас при объявлении переменных предпочтение отдается let
. Это совершенно не удивительно, потому что оператор let
и задумывался как улучшенный вариант var
. Помимо прочего, он решает проблему, которую мы осветили в предыдущем разделе. Давайте посмотрим, каким образом он это делает.
let имеет блочную область видимости
Блок это отрывок кода внутри фигурных скобок. Любой код, окруженный фигурными скобками, — блок.
Переменная, объявленная в блоке кода при помощи оператора let
, доступна для использования только в рамках этого блока кода.
(Отличие от просто локальной переменной в том, что здесь область видимости не функция, а блок кода. Причем этот блок может иметь и вложенные блоки. — Прим. ред.)
Давайте рассмотрим пример.
let greeting = "say Hi"; let times = 4; if (times > 3) { let hello = "say Hello instead"; console.log(hello);//"say Hello instead" } console.log(hello) // hello is not defined
Мы видим, что использование переменной hello
вне ее блока (т. е., за пределами кода, ограниченного фигурными скобками, в котором была объявлена переменная) приводит к ошибке. Это потому, что переменные, объявленные при помощи let
, имеют блочную область видимости.
Переменные, объявленные при помощи let, могут обновляться, но не объявляться повторно
Как и переменные, объявленные при помощи оператора var
, переменные, объявленные с использованием let
, могут обновляться в пределах их видимости. Но в отличие от var
, let
не позволяет повторно объявлять переменную в рамках ее области видимости.
Так что этот код будет работать нормально:
let greeting = "say Hi"; greeting = "say Hello instead";
а этот вернет ошибку:
let greeting = "say Hi"; let greeting = "say Hello instead";//error: Identifier 'greeting' has already been declared
Тем не менее, если объявлять переменную с одним именем в разных областях видимости, ошибки не будет:
let greeting = "say Hi"; if (true) { let greeting = "say Hello instead"; console.log(greeting);//"say Hello instead" } console.log(greeting);//"say Hi"
Почему здесь нет ошибки? Потому что эти два экземпляра переменных находятся в разных областях видимости и вследствие этого воспринимаются как совершенно разные переменные.
В связи с этой особенностью оператор let
будет лучшим выбором, чем var
. Используя let
, вам не нужно беспокоиться о том, использовали ли вы это имя переменной раньше, потому что каждая такая переменная существует только в рамках своего блока.
Кроме того, поскольку переменную в рамках ее области видимости нельзя объявить повторно, исчезает проблема, которая возникала при использовании var.
Поднятие let
Объявления переменных при помощи let
тоже поднимаются вверх. Но в отличие от переменных, объявленных при помощи var, которые могут инициализироваться как undefined
, ключевое слово let
такого не позволяет. Так что если вы попытаетесь использовать переменную, объявленную при помощи let
, до ее декларирования, вы получите Reference Error
.
Const

Переменные, объявленные с использованием const
, содержат постоянные значения. Объявление переменных при помощи const
имеет некоторое сходство с объявлением при помощи let
.
Переменные, объявленные при помощи const, имеют блочную область видимости
Как и переменные, объявленные при помощи оператора let
, переменные, объявленные с использованием const
, доступны только в рамках того блока, внутри которого их объявили.
Переменные, объявленные при помощи const, нельзя обновить или объявить заново
То есть, значение переменной, объявленной при помощи const
, остается неизменным внутри ее области видимости. Эту переменную нельзя объявить заново или обновить. Поэтому, объявляя переменную при помощи const
, мы не можем сделать ни так:
const greeting = "say Hi"; greeting = "say Hello instead";//error : Assignment to constant variable.
ни так:
const greeting = "say Hi"; const greeting = "say Hello instead";//error : Identifier 'greeting' has already been declared
Вследствие этого каждая переменная, объявленная с использованием const
, должна быть инициализирована при объявлении.
Это поведение несколько отличается, когда речь идет об объектах, объявленных при помощи const
. Хотя такой объект не может быть обновлен, свойства этого объекта обновлять можно. То есть, если мы объявим объект следующим образом:
const greeting = { message : "say Hi", times : 4 }
мы не сможем сделать так:
const greeting = { words : "Hello", number : "five" }//error : Assignment to constant variable.
а вот так — сможем:
greeting.message = "say Hello instead";
Значение greeting.message
обновится без всяких ошибок.
Поднятие const
Переменные, объявленные при помощи оператора const
, тоже поднимаются вверх, но при этом не инициализируются.
Итоги
На случай, если вы все же не уловили разницу между var
, let
и const
, повторим:
- Переменные, объявленные при помощи
var
, имеют глобальную или локальную (в рамках функции) область видимости. Если вы объявляете переменные с использованиемlet
илиconst
, их область видимости будет блочной. - Переменные, объявленные при помощи
var
, могут обновляться и объявляться заново. Использованиеlet
позволяет обновлять переменную, но не объявлять заново, а использованиеconst
не предполагает ни того, ни другого. - Переменные всех видов поднимаются в верх своей области видимости. Но переменные, объявленные при помощи
var
, инициализируются какundefined
, а объявленные с использованиемlet
илиconst
— не инициализируются. - При помощи
var
илиlet
можно объявлять переменные без их инициализации, но если вы объявляете переменную при помощиconst
, она должна инициализироваться при объявлении.
Хорошая статья без воды. С удовольствием прочитал 🙂
Классно структурировал статью. И хорошие примеры. Спасибо.
Наверно лучшая статья, которая мне попалась на эту тему. Спасибо!
Отличная статья! Очень помогла разобраться! Спасибо за примеры, автор!
Что то у меня в const преблем при второй записи небыло! Перезаписалась без проблем!
const Array = [1,2,3,4,5];
Array[3] = 33;
// Ошибки нет! После массив содержит [1,2,33,4,5]
Вопрос: Нах.. этот const нужен ???