var, let, const: в чем разница?
Сегодня мы поговорим о важной теме, которую необходимо знать разработчику JavaScript. Каждый день вы используете var, let или/и const, но знаете ли вы разницу между ними. Об этом сегодня мы и поговорим.
var
Оператор var
в наше время используется все реже, но это не значит, что его использование вредно.
На самом деле есть несколько хитростей, которые могут сделать код менее предсказуемым.
Переприсваивание
В переменную, объявленную через var, можно присвоить другое значение:
var myVariable = "First value"; myVariable = "Second value";
*Примечание: Вы не обязаны инициализировать значением:
var notInitializedVar;
Объявление var
с одинаковым именем
Вы можете объявить несколько переменных с одинаковым именем:
var redeclaredVar = 'Первое объявление'; var redeclaredVar = 'Второе объявление';
Область видимостиvar
Область использования var
зависит от того, где она объявлена.
Когда var объявлен внутри функции, его областью видимости будет вся функция. Если вы объявили переменную с помощью var внутри if
, переменная будет доступна и за пределами if
:
function myDummyFunction() { if (true) { var myVariable = "Переменная, объявленная с помощью var"; } console.log(myVariable); } // Вывод "Переменная, объявленная с помощью var" myDummyFunction();
Примечание: Переменная, конечно же также доступна во внутренних "блоках":
function myDummyFunction() { var myVariable = "Переменная, объявленная с помощью var"; if (true) { console.log(myVariable); } } // Вывод "Переменная, объявленная с помощью var" myDummyFunction();
За пределами функции
Когда мы объявляем переменную с помощью var вне функции, переменная будет глобальной переменной.
Например, если вы наберете в отладчике вашего браузера:
var myGlobalVariable = "Привет, я буду доступен в этом окне"; // Выведет "Привет, я буду доступен в этом окне". console.log(window.myGlobalVariable);
Предупреждение: При работе с модулями ES и модулями commonJS эта переменная будет привязана только к модулю.
Примечание: Для того и создано Немедленно Вызванное Функциональное Выражение (Immediately Invoked Function Expressio - IIFE), чтобы переменная не находилась в глобальной области видимости и не конфликтовала с переменными других библиотек.
Hoisting (Поднятие)
Во-первых, давайте определим, что такое поднятие: это поведение, позволяющее автоматически помещать переменную или функцию в начало файла.
Благодаря поднятию, вы можете объявить свою функцию (стандартно объявленную, Function Declaration) после ее использования:
hoistedFunction(); function hoistedFunction() { console.log("Меня могут вызвать до моего объявления."); }
Особенность var
заключается в том, что переменная располагается в начале файла или функции (если она объявлена внутри функции) и инициализируется значением undefined.
// Будет выведено "undefined" console.log(myHoistedVar); var myHoistedVar = "Я - hoisted и инициализированный var";
function myDummyFunction() { // Переменная объявлена внутри if, но условие в if всегда ложно console.log(myVariable); if (false) { var myVariable = "Переменная, объявленная с помощью var"; } } // Будет выведено "undefined" myDummyFunction();
Назначение неквалифицированного идентификатора
В нестрогом режиме (без "use strict";
), если вы объявили переменную только с ее меткой и без классификатора (var
, let
или const
), она будет автоматически создана какvar
:
unqualifiedVar = "Я буду автоматически проходить квалификацию с var в нестрогом режиме"; //Это будет трансформировано в var unqualifiedVar = "Я буду автоматически проходить квалификацию с var в нестрогом режиме";
Предупреждение: В строгом режиме это не будет работать и вызовет ошибку ReferenceError.
"use strict"; // В консоли вы увидите что-то вроде: // Uncaught ReferenceError: unqualifiedVar не определена unqualifiedVar = "Вызовет ошибку ReferenceError";
let
В повседневной жизни вы, вероятно, чаще используете переменную let
, чем var
. Но давайте освежим наши знания об этой переменной:
Переназначение
Как и var
, вы можете переприсвоить значение в переменную, объявленную с помощью let
:
let myVariable = "First value"; myVariable = "Second value";
Здесь кроется одно из главных отличий от var
. Переменная, определенная с помощью let
, будет блочной (т.е. будет доступна только внутри текущей родительской фигурной скобки).
function myDummyFunction() { let myVariable = "Переменная let"; if (true) { console.log(myVariable); } } // Будет выведено: Переменная let myDummyFunction();
В отличие от var
, она вызовет ошибку ReferenceError
, если вы попытаетесь обратиться к переменной, объявленной во внутреннем блоке:
function myDummyFunction() { if (true) { let myVariable = "Переменная let"; } console.log(myVariable); } // В консоли вы увидите что-то вроде // Uncaught ReferenceError: myVariable не определена myDummyFunction();
Примечание: Переменная, объявленная с помощью let
, никогда не будет глобальной.
Нельзя пересоздавать одну и ту же переменную
В отличие от var
вы не можете создать другую переменную с тем же именем. В противном случае, в консоли появится SyntaxError.
let myLetVariable = "Первое значение"; // В консоли вы увидите что-то вроде // Uncaught SyntaxError: Идентификатор 'myLetVariable' уже был объявлен let myLetVariable = "Второе значение";
А как насчет hoisting?
Переменная, созданная с помощью let
(как и const
), на самом деле также поднимается наверх, как и var
, однако, пока мы не дойдем до создания переменной в коде, эта переменная будет находиться во временной мертвой зоне (Temporal Dead Zone или TDZ)
Пока переменная не инициализирована, при попытке обращения к ней будет возникать ошибка ReferenceError
.
console.log(myLetVariable); // В консоли вы увидите что-то вроде // Uncaught ReferenceError: myLetVariable не определена let myLetVariable = "Некоторое значение"; // Отсюда больше никаких TDZ
Такое поведение называется Временная мертвая зона (TDZ).
Если вы спросите, почему используется термин "временная"?
На самом деле это потому, что все зависит от того, когда выполняется код. Например:
setTimeout(() => console.log(myLetVariable), 500); let myLetVariable = "Некоторое значение"; // Через 500 мс вы увидите // "Некоторое значение" выводится в консоль
const
Переменная, объявленная с помощью const
, имеет очень похожие свойства, что и let
. Единственное различие заключается в переприсваивании в переменную и инициализации.
Нет переприсваивания
При использовании переменной, объявленной с const
, невозможно присвоить в эту переменную другое значение:
const myConstVariable = "Первое значение"; // В консоли вы увидите что-то вроде // Uncaught TypeError: Присвоение постоянной переменной myConstVariable = "Второе значение";
Предупреждение: Переменная, объявленная с const
, является изменяемой:
const person = {}; // Здесь происходит мутация person.firstName = "Роман";
Инициализация
Вы должны инициализировать переменную, обозначенную const
, иначе возникнет SyntaxError.
// В консоли вы увидите что-то вроде // Uncaught SyntaxError: Отсутствующий инициализатор в объявлении const const uninitializedConst;
Заключение
Надеюсь, в вашей голове все прояснилось. Если вам нужно что-то запомнить, я думаю, это будет то, что область видимости между var
и let
/const
различна.var
имеет область видимости функции, когда объявлена внутри функции, и глобальную область видимости, когда вне ее. let
и const
имеют область видимости блока.
Переменная let
/var
может быть переприсвоена, в отличие от const
. Но будьте внимательны, переменная, объявленная с const
, не является неизменяемой.
Все три переменные являются hoisted, но var
инициализируется в undefined
, "всплывая наверх", в отличие от let
и const
, которые этого не делают.
Источник: https://dev.to/romaintrotard/var-let-const-what-s-the-difference-2eh0