Const, Var или Let в JavaScript: полное руководство на все времена
До появления ECMAScript6, декларации var правили миром. Были проблемы, связанные с переменными, объявленными с помощью var. Но пришло время появления новых способов объявления переменных. В рамках ES6, для объявления переменных были добавлены let и const.
Вы будете иметь кристально четкое представление об области видимости и использовании var, let и const. Во время чтения, обратите внимание на различия между ними, чтобы потом кодировать как профессионал.
Var
Содержание статьи:
- 1 Var
- 2 Область действия
- 3 Повторное объявление и обновление переменных Var
- 4 Hoisting переменных Var
- 5 Проблема с var
- 6 Hoisting переменных var
- 7 Почему это случилось?
- 8 Let
- 9 Let имеет блочную область видимости
- 10 Обновить, но не объявлять повторно переменную let
- 11 Hoisting переменных Let
- 12 Const
- 13 Область видимости переменных сonst
- 14 Переменные сonst повторно не объявляются и не обновляют свое значение
- 15 Hoisting переменных const
- 16 Выводы
- 17 Заключение
Представьте, что вы играете персонажем в ролевой игре и хотите купить зелья у торговца гоблинами. Кто-то, не зная разницы между var, let и const разработал магазин и приведенные здесь примеры обьясняют, что плохо, что хорошо, и почему это так.
Вы должны понять, как работает var, прежде чем мы обсудим упомянутые выше вопросы.
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Область действия
Область действия переменной указывает, где вы можете ее использовать. Var имеет глобальную область видимости или область видимости функции (локальную).
Глобальная область видимости — когда переменная var объявляется вне функции. Объявление var вне блока функции, делает переменную доступной для использования во всем теле вашего кода.
Переменная, объявленная с помощью var, является функциональной, когда вы помещаете ее внутрь функции. Она доступна только в этой функции. Чтобы лучше понять, посмотрите на пример ниже.
JavaScript var priceTag = 30; function newFunction() { var name = ‘Health Potion’; }
12345 | var priceTag = 30; function newFunction() { var name = ‘Health Potion’;} |
Здесь переменная priceTag имеет глобальную область видимости, потому что она была объявлена и инициализирована вне функции newFunction(), в то время как name имеет область видимости функции. Вы не можете получить доступ к переменной name вне newFunction(). Попробуйте получить к ней доступ и…
JavaScript var priceTag = 30; function newFunction() { var name = ‘Health Potion’; } console.log(name); // error: name is not defined
123456 | var priceTag = 30; function newFunction() { var name = ‘Health Potion’;}console.log(name); // error: name is not defined |
… Вы только что получили ошибку. Результат – переменная name недоступна снаружи newFunction().
Повторное объявление и обновление переменных Var
Вы можете сделать это в той же области и не получите ошибки.
JavaScript var priceTag = 30; var priceTag = 45;
12 | var priceTag = 30;var priceTag = 45; |
Также возможно следующее, не вызывая ошибки:
JavaScript var priceTag = 30; priceTag = 45;
12 | var priceTag = 30;priceTag = 45; |
Hoisting переменных Var
Hoisting (подъем) — это механизм JavaScript, в котором переменные и объявления функций перемещаются в верхнюю часть своей области видимости перед выполнением кода. Это означает, что если вы сделаете это:
JavaScript function HealthPotion(){ //some code var priceTag = 30; //some more code }
1234567 | function HealthPotion(){ //some code var priceTag = 30; //some more code} |
JavaScript интерпретирует это следующим образом:
JavaScript function HealthPotion(){ var priceTag; //some code priceTag = 30; //some more code }
12345678 | function HealthPotion(){ var priceTag; //some code priceTag = 30; //some more code} |
Добавьте console.log(priceTag) во вторую строку первого примера и вызовите функцию, после чего вы получите undefined доступ к priceTag.
Код вроде работает, и ошибок не возникает. Но переменная инициализируется позже (помещая в нее значение).
Интуитивно не понятно, что переменная существует до ее объявления, но в JavaScript это возможно. Переменную можно использовать в самом начале функции, хотя ее можно объявить в последней строке тела функции. Помните, что переменная будет неопределенной, пока не будет выполнена строка инициализации.
Проблема с var
Слабым местом var является переопределение уже определенной глобальной переменной в другой области видимости:
JavaScript var priceTag = 30; var amountToBuy = 4; if (amountToBuy > 3) { var priceTag = 45; } console.log(priceTag) // The price is «45»
12345678 | 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 может привести к ошибкам и очень удивить вас.
JavaScript var items = [«HealingPotion», «Gold»]; for (var i = 0; i < items.length; i++) { setTimeout(function () { console.log(«Bought the following Item:» + items[i]) }, i * 1000); }
1234567 | 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. Вот доказательство:
Почему это случилось?
Функция определяет область действия переменной. Блок (это наш цикл for) не может определять область для переменной, объявленной с помощью var.
Это разрешено только функциям. Текущий индекс i существует в глобальном пространстве и только один. Не один раз за итерацию блока. Так как setTimeout приостановит выполнение на i * 1000 миллисекунд, прежде чем он дойдет до распечатки, текущий индекс i будет иметь значение 2.
В массиве items всего два элемента, их индексы – 0 и 1. Результат — undefined качестве возврата. Закрытие позволяет поместить содержимое цикла внутри анонимной функции и вызвать ее с текущим индексом в качестве параметра. Оно сохраняет состояние внешнего блока во внутреннем блоке setTimeout, то есть анонимной функции.
JavaScript 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); }
123456789 | 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);} |
Let
Вы всегда должны отдавать предпочтение объявлению let. Это не удивительно, поскольку let является улучшением var. Let также решает проблему Hoisting, с которой мы столкнулись с var.
Let имеет блочную область видимости
Блок представляет собой фрагмент кода, ограниченный { }.
Блок живет в фигурных скобках.
Все, что находится в фигурных скобках, является блоком.
Переменная let, которую вы объявляете внутри блока, доступна для использования только в этом блоке. Позвольте мне объяснить это на примере:
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
JavaScript 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
123456789 | 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 не может быть повторно объявлена в пределах своей области видимости. Итак, пока это будет работать:
JavaScript let priceTag = 30; priceTag = 45;
12 | let priceTag = 30;priceTag = 45; |
это вернет ошибку:
JavaScript let priceTag = 30; let priceTag = 45;
12 | let priceTag = 30;let priceTag = 45; |
Если одна и та же переменная определена в разных областях, ошибки не будет, как вы видели на примере. А как насчет доступа к переменным с блочной областью видимости извне?
JavaScript 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
123456789 | 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, вы не можете сделать такого:
JavaScript const priceTag = 30; priceTag = 45;// error: Assignment to constant variable
12 | const priceTag = 30;priceTag = 45;// error: Assignment to constant variable |
либо такого:
JavaScript const priceTag = 30; const priceTag = 45 // error: Identifier ‘priceTag’ has already been declared
12 | const priceTag = 30;const priceTag = 45 // error: Identifier ‘priceTag’ has already been declared |
Следовательно, каждое объявление сonst должно быть инициализировано во время объявления. Это поведение немного отличается, если дело касается объектов, объявленных с помощью const. Хотя вы не можете обновить ссылку на объект, вы можете обновить свойства самого объекта. Следовательно, если вы объявляете объект const следующим образом:
JavaScript const potion = { name: «Health Potion», priceTag: 30 }
1234 | const potion = { name: «Health Potion», priceTag: 30} |
вы не можете сделать так:
JavaScript const potion = { name: «Mana Potion», priceTag: 60 }
1234 | const potion = { name: «Mana Potion», priceTag: 60} |
Но вы можете сделать вот так:
JavaScript potion.priceTag = 60;
1 | 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
Источник: webformyself.com