Const, Var или Let в JavaScript: полное руководство на все времена

От автора: переменная var кажется Вам идентичной переменной let? Вы создали переменную const, но ее свойства были изменены? var, let и const до сих пор являются для вас загадкой?

До появления ECMAScript6, декларации var правили миром. Были проблемы, связанные с переменными, объявленными с помощью var. Но пришло время появления новых способов объявления переменных. В рамках ES6, для объявления переменных были добавлены let и const.

Вы будете иметь кристально четкое представление об области видимости и использовании var, let и const. Во время чтения, обратите внимание на различия между ними, чтобы потом кодировать как профессионал.

Var

Представьте, что вы играете персонажем в ролевой игре и хотите купить зелья у торговца гоблинами. Кто-то, не зная разницы между var, let и const разработал магазин и приведенные здесь примеры обьясняют, что плохо, что хорошо, и почему это так.

Вы должны понять, как работает var, прежде чем мы обсудим упомянутые выше вопросы.

Область действия

Область действия переменной указывает, где вы можете ее использовать. Var имеет глобальную область видимости или область видимости функции (локальную).

Глобальная область видимости — когда переменная var объявляется вне функции. Объявление var вне блока функции, делает переменную доступной для использования во всем теле вашего кода.

Переменная, объявленная с помощью var, является функциональной, когда вы помещаете ее внутрь функции. Она доступна только в этой функции. Чтобы лучше понять, посмотрите на пример ниже.

var priceTag = 30; function newFunction() { var name = 'Health Potion';
}

Здесь переменная priceTag имеет глобальную область видимости, потому что она была объявлена и инициализирована вне функции newFunction(), в то время как name имеет область видимости функции. Вы не можете получить доступ к переменной name вне newFunction(). Попробуйте получить к ней доступ и…

var priceTag = 30; function newFunction() { var name = 'Health Potion';
}
console.log(name); // error: name is not defined

… Вы только что получили ошибку. Результат – переменная name недоступна снаружи newFunction().

Повторное объявление и обновление переменных Var

Вы можете сделать это в той же области и не получите ошибки.

var priceTag = 30;
var priceTag = 45;

Также возможно следующее, не вызывая ошибки:

var priceTag = 30;
priceTag = 45;

Hoisting переменных Var

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

function HealthPotion(){ //some code var priceTag = 30; //some more code
}

JavaScript интерпретирует это следующим образом:

function HealthPotion(){ var priceTag; //some code priceTag = 30; //some more code
}

Добавьте console.log(priceTag) во вторую строку первого примера и вызовите функцию, после чего вы получите undefined доступ к priceTag.

Код вроде работает, и ошибок не возникает. Но переменная инициализируется позже (помещая в нее значение).

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

Проблема с var

Слабым местом var является переопределение уже определенной глобальной переменной в другой области видимости:

var priceTag = 30;
var amountToBuy = 4; if (amountToBuy > 3) { var priceTag = 45;
} console.log(priceTag) // The price is "45"

Темный торговец не дал нам скидки на покупку четырех зелий. Он схитрил, и мы должны заплатить 45 золотых за каждое зелье!

Итак, поскольку amountToBuy > 3 возвращает true, priceTag переопределяется на 45. Хотя это не проблема, если вы сознательно хотите переопределить значение amountToBuy, но это становится проблемой, когда вы не знаете, что переменная priceTag уже была определена ранее.

С помощью небольшого фрагмента, подобного этой статье, вы можете увидеть проблему. Представьте себе такое в более крупной кодовой базе …

Если вы использовали priceTag в других местах кода, вы можете быть удивлены полученым результатом. Это, скорее всего, вызовет ошибки в вашем коде. Вот почему необходимы let и const.

Hoisting переменных var

Это дополнительная информация, вам нужно знать, что такое блок, но не обязательно понимать различия между let, var и const. В циклах Hoisting может привести к ошибкам и очень удивить вас.

var items = ["HealingPotion", "Gold"]; for (var i = 0; i < items.length; i++) { setTimeout(function () { console.log("Bought the following Item:" + items[i]) }, i * 1000);
}

Этот код не будет распечатывать пунктов Healing Potion и Gold, как вы, вероятно, предполагаете. Вместо этого вы получаете два раза undefined. Вот доказательство:

Const, Var или Let в JavaScript: полное руководство на все времена

Почему это случилось?

Функция определяет область действия переменной. Блок (это наш цикл for) не может определять область для переменной, объявленной с помощью var.

Это разрешено только функциям. Текущий индекс i существует в глобальном пространстве и только один. Не один раз за итерацию блока. Так как setTimeout приостановит выполнение на i * 1000 миллисекунд, прежде чем он дойдет до распечатки, текущий индекс i будет иметь значение 2.

В массиве items всего два элемента, их индексы – 0 и 1. Результат — undefined качестве возврата. Закрытие позволяет поместить содержимое цикла внутри анонимной функции и вызвать ее с текущим индексом в качестве параметра. Оно сохраняет состояние внешнего блока во внутреннем блоке setTimeout, то есть анонимной функции.

var items = ["HealingPotion", "Gold"]; for (var i = 0; i < items.length; i++) { (function (val) { setTimeout(function () { console.log("Bought the following Item:" + items[val]) }, i * 1000); })(i);
}

Const, Var или Let в JavaScript: полное руководство на все времена

Let

Вы всегда должны отдавать предпочтение объявлению let. Это не удивительно, поскольку let является улучшением var. Let также решает проблему Hoisting, с которой мы столкнулись с var.

Let имеет блочную область видимости

Блок представляет собой фрагмент кода, ограниченный { }.

Блок живет в фигурных скобках.

Все, что находится в фигурных скобках, является блоком.

Переменная let, которую вы объявляете внутри блока, доступна для использования только в этом блоке. Позвольте мне объяснить это на примере:

let priceTag = 30;
let amountToBuy = 4; if (amountToBuy > 3) { let priceTag = 45; console.log('Block PriceTag', priceTag); // Block PriceTag 45
} console.log('Global PriceTag', priceTag) // Global PriceTag 30

Подозрительный торговец больше нас не обманет!

Вы можете видеть, что использование priceTag вне блока возвращает 30. Это потому, что переменные let имеют блочную область видимости.

Почему при этом не возникла ошибка? Потому что оба экземпляра рассматриваются как разные переменные, поскольку имеют разные области действия.

let является лучшим выбором чем var. Когда вы используете let, вы не беспокоитесь об использовании имени переменной раньше в коде. Нужно быть осторожным только в рамках блока.

Обновить, но не объявлять повторно переменную let

Точно так же как с var, переменная объявленная с помощью let, может быть обновлена в пределах своей области видимости.

В отличие от var, переменная let не может быть повторно объявлена в пределах своей области видимости. Итак, пока это будет работать:

let priceTag = 30;
priceTag = 45;

это вернет ошибку:

let priceTag = 30;
let priceTag = 45;

Если одна и та же переменная определена в разных областях, ошибки не будет, как вы видели на примере. А как насчет доступа к переменным с блочной областью видимости извне?

let priceTag = 30;
let amountToBuy = 4; if (amountToBuy > 3) { let newPriceTag = 45; console.log('Block PriceTag', newPriceTag); // Block PriceTag 45
} console.log('Global PriceTag', newPriceTag) // newPriceTag is not defined

Кроме того, поскольку переменная не может быть объявлена более одного раза в любой области видимости, проблема, описанная ранее, возникающая с var, теперь не повторится.

Hoisting переменных Let

Так же, как с var, переменные let перемещаются в верхнюю часть своей области видимости. В отличие от var которые инициализируется как undefined, ключевое слово let не инициализируется. Если вы попытаетесь использовать переменную let перед объявлением, вы получите Reference Error.

Const

Переменные, объявленные как const сохраняют постоянное значение. Декларации сonst имеют некоторое сходство с декларациями let.

Область видимости переменных сonst

К переменным сonst можно получить доступ только в том блоке, в котором они были объявлены. Аналогично как и с переменными let.

Переменные сonst повторно не объявляются и не обновляют свое значение

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

const priceTag = 30;
priceTag = 45;// error: Assignment to constant variable

либо такого:

const priceTag = 30;
const priceTag = 45 // error: Identifier 'priceTag' has already been declared

Следовательно, каждое объявление сonst должно быть инициализировано во время объявления. Это поведение немного отличается, если дело касается объектов, объявленных с помощью const. Хотя вы не можете обновить ссылку на объект, вы можете обновить свойства самого объекта. Следовательно, если вы объявляете объект const следующим образом:

const potion = { name: "Health Potion", priceTag: 30
}

вы не можете сделать так:

const potion = { name: "Mana Potion", priceTag: 60
}

Но вы можете сделать вот так:

potion.priceTag = 60;

Это обновит значение potion.priceTag без возврата ошибки. Мрачный гоблин снова обманул нас! Теперь надо покупать простое зелье здоровья за 60 вместо 30 золотых …

Hoisting переменных const

Так же, как let, переменные const перемещаются в верхнюю часть своей области видимости, но не инициализируются.

Выводы

Переменные var живут в глобальной области видимости или области видимости функции.

Let и const имеют блочную область видимости.

Вы можете обновлять переменные var и повторно объявлять их в пределах своей области видимости.

Вы также можете обновлять, но не объявлять повторно переменные let.

Переменные const нельзя ни обновить, ни повторно объявить.

Все подлежат поднятию в верхнюю часть своей области видимости (hoisting).

Переменные var инициализируются с помощью undefined, переменные let и const не инициализируются.

Var и let могут быть объявлены без инициализации

const должены быть инициализированы во время объявления.

Заключение

Var используется в основном новичками, потому что переменные var кажется лучшим/первым выбором, или же вы начали кодировать в JavaScript еще тогда, когда выбора еще не было.

Тем не менее, декларирование var легко может быть ошибочно воспринято как краткий термин для variable или variant, я использовал var когда был новичком в JavaScript в 2015 году.

Сегодня, var больше не рекомендуется использовать. Выбросте его из набора инструментов или, по крайней мере, используйте его для устаревшего кода. Для обработки унаследованного кода знания о hoisting и var являются обязательными.

В настоящее время, линтеры делают нашу жизнь проще, когда они настроены правильно, и даже если нет, сохраните свое время используя const> let> var. Спасибо за чтение :)

Автор: Arnold Abraham

Источник: javascript.plainenglish.io

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен