Var, Let и Const: в чем разница?

1
2951
views

Перевод статьи «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, она должна инициализироваться при объявлении.

1 КОММЕНТАРИЙ

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here