Выбрать главу

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.

Прежде чем вы продолжите читать дальше, убедитесь, что весь пройденный материал вам понятен. Если у вас есть какие-то вопросы, обращайтесь на форум https://forum.kirupa.com, где я и другие разработчики с радостью помогут вам.

КОРОТКО О ГЛАВНОМ

Место размещения переменных в коде имеет огромное влияние на то, где они могут использоваться. Переменные, объявленные глобально, доступны по всему приложению. Переменные, объявленные локально, — только внутри области, в которой расположены. Внутри диапазона глобальных и локальных переменных у JavaScript есть огромное количество действий в запасе.

Эта глава представила обзор аспектов влияния области переменных на ваш код. В ближайшем будущем вам предстоит встретиться с некоторыми наиболее актуальными из этих аспектов.

Глава 9. Замыкания

Вероятно, что к этому моменту вы уже знаете все о функциях и обо всех их забавных особенностях. Важная часть работы с функциями, JavaScript и (возможно) жизнью в целом — это понимание замыканий. На рис. 9.1 замыкание обозначено серой областью, в которой пересекаются области функций и переменных.

Рис. 9.1. Замыкания

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

Поехали!

Функции внутри функций

Первое, что мы сделаем, — проясним, что происходит, когда вы используете функции внутри функций, причем внутренняя функция возвращается. Для начала рассмотрим короткий пример.

Взгляните на этот код:

function calculateRectangleArea(length, width) {

return length * width;

}

let roomArea = calculateRectangleArea(10, 10);

alert(roomArea);

Функция calculateRectangleArea получает два аргумента и возвращает результат их умножения туда, откуда пришел вызов. В данном примере роль стороны, направившей вызов, играет переменная roomArea.

После выполнения этого кода переменная roomArea содержит результат умножения 10 на 10, равный 100 (рис. 9.2).

Рис. 9.2. Результат roomArea

Как вы знаете, функция может вернуть практически что угодно. В данном случае мы вернули число. Вы так же легко можете вернуть текст (то есть строку), значение undefined, пользовательский объект и т. д. До тех пор пока код, вызывающий функцию, знает, как поступить с возвращаемым ей результатом, вы можете делать практически все, что пожелаете. Вы даже можете вернуть другую функцию. На этом моменте остановимся поподробнее.