JavaScript с нуля - [19]

Шрифт
Интервал

функции alert.

А что насчет следующей ситуации?

function isThePriceRight(cost) {

let total = cost + 1;


if (total > 3) {

let warning = true;

alert(total);

} else {

alert("Not enough!");

}


alert(warning);

}


isThePriceRight(4);

У нас есть переменная warning, объявленная внутри блока if, а еще — функция alert, которая пытается вывести значение warning. В этом случае, так как мы пытаемся обратиться к переменной warning в блоке, находящемся вне блока, в котором она была объявлена, функция alert не будет отображать значение true. Учитывая то, где находится функция alert, переменная warning находится вне области видимости.

объявление переменных с ключевым словом var

Несколько абзацев выше я упомянул вскользь, что переменные когда-то объявлялись с помощью ключевого слова var. Ключевые слова let (и const) были введены позднее для облегчения объявления переменных. Если вы до сих пор используете var, пора переходить на let. Мы еще не обсуждали, почему let — более предпочтительный вариант, и решили, что обсудим это позже, когда начнем рассматривать области переменных подробнее. Что ж, настал этот момент!

Переменные, объявленные с var, распространяются на область функции. Они не распространяются на блоки, подобные инструкциям if и else. Если мы изменим последний пример, объявив в нем переменную warning с var вместо let, то код будет выглядеть так:

function isThePriceRight(cost) {

let total = cost + 1;


if (total > 3) {

var warning = true;

alert(total);

} else {

alert("Not enough!");

}


alert(warning);

}


isThePriceRight(4);

В изначальном варианте этого кода функция alert в отношении переменной warning ничего бы не отобразила, так как эта переменная, будучи объявленной с let, оказывалась вне области видимости. При использовании же var ситуация меняется и вы увидите отображение true. В этом и есть отличие между var и let. Область видимости переменных, объявленных с var, ограничивается уровнем функций, поэтому если переменная объявляется в любом месте внутри функции, то считается, что она находится в области видимости. Область же видимости переменных, объявленных с let, как мы увидели ранее, определяется уровнем блока.

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

Как JavaScript обрабатывает переменные

Если вам показалось, что логика областей блока из предыдущего раздела выглядит странно, значит, вы еще не видели следующий пример. Взгляните на этот код:

let foo = "Hello!";

alert(foo);

Глядя на него, мы можем обоснованно утверждать, что отобразится значение Hello! и в целом будем правы. А что, если переместить объявление и инициализацию переменной в конец?

alert(foo);

let foo = "Hello!";

В этом случае код выдаст ошибку. Доступ к переменной foo осуществляется без обращения к ней. А теперь давайте заменим let на var, получив следующее:

alert(foo);

var foo = "Hello!";

При выполнении этого варианта кода его поведение будет отличаться от предыдущего и вы увидите отображение undefined. Что конкретно здесь происходит?

Когда JavaScript при выполнении достигает определенной области (глобальной, функции и т. д.), то первое, что он делает, — полностью сканирует тело кода в поиске объявленных переменных. Если он встречает переменные, объявленные с var, то по умолчанию инициализирует их как undefined. Если же они объявлены с let или const, он оставляет их полностьюнеинициализированными. При завершении он перемещает все встреченные переменные в верхнюю часть соответствующей им области, которой в случае с let и const является ближайший блок, а в случае с var — ближайшая функция.

Давайте подробнее рассмотрим, что это значит. Изначально наш код выглядит так:

alert(foo);

let foo = "Hello!";

Когда JavaScript приступает к его обработке, код принимает следующий вид:

let foo;

alert(foo);

foo = "Hello!";

Несмотря на то что переменная foo была объявлена в нижней части кода, она смещается вверх. Формально это называется поднятием переменной. Особенность let и const в том, что при поднятии переменные остаются неинициализированными. Если вы попробуете обратиться к неинициализированной переменной, то код выдаст ошибку и прекратит выполнение. Если мы изменим предыдущий пример, используя var, то в итоге для JavaScript код будет выглядеть так:

var foo = undefined;

alert(foo);

foo = "Hello!";

Переменная по-прежнему поднимается, но при этом инициализируется как undefined, благодаря чему код продолжает выполнение.

Главная мысль из всего этого: пожалуйста, объявляйте и инициализируйте переменные прежде, чем их использовать. Несмотря на то что JavaScript способна в некоторой степени справиться с работой в тех случаях, когда мы пренебрегаем данными действиями, это лишь добавит еще больше путаницы.

Замыкания

Ни одно обсуждение области переменных не будет полным, если не рассмотреть замыкания. Сейчас я не стану объяснять эту тему, прибережем ее для главы 9.

Прежде чем вы продолжите читать дальше, убедитесь, что весь пройденный материал вам понятен. Если у вас есть какие-то вопросы, обращайтесь на форум


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.