Знаете ли вы, что JavaScript перемещает объявления переменных и функций наверх?
Подъем - это стандартное поведение JavaScript, заключающееся в перемещении всех объявлений в верхнюю часть области видимости.
Подъем происходит потому, что JavaScript хочет найти все переменные и функции перед запуском кода, чтобы зарезервировать для них память. Однако такое поведение может сбить с толку новичков.
Итак, в этой статье я расскажу о подъеме JavaScript, о том, как он работает и как преодолеть путаницу, связанную с подъемом.
Подъем переменных в JavaScript
Давайте начнем с того, что посмотрим, что означает подъем при работе с переменными в JavaScript.
Но сначала взгляните на этот обычный фрагмент кода:
var name = "Matt"; console.log(name);
Выход:
Matt
Ничего особенного там не происходит. Вы создаете переменную и регистрируете ее в консоли.
Но давайте изменим порядок выражений:
console.log(name); var name = "Matt";
Что происходит сейчас? Разве это не должно вызывать ошибку, потому что вы пытаетесь использовать переменную до ее определения?
Удивительно, но результат:
undefined
Это означает, что JavaScript должен заранее знать о переменной name
. В противном случае этот фрагмент кода приведет к ошибке ссылки.
Это действительно так. В JavaScript переменные и функции поднимаются вверху области. Они физически не перемещаются наверх. Хотя, можно думать об этом как о таковом.
В приведенном выше примере подъем действует следующим образом:
var name; console.log(name); name = "Matt";
Переменная name
объявляется первой без значения. Это означает, что name
становится undefined
, когда он зарегистрирован в консоли.
Подъем происходит потому, что JavaScript хочет зарезервировать место для переменных и функций перед присвоением им значений.
Подъем может вызвать путаницу
Давайте посмотрим на примере, где подъем может сбить с толку, и как с этим справиться.
Взгляните на этот фрагмент кода. Как вы думаете, что он входит в консоль?
Вы можете подумать, что он печатает 1
по той причине, что этот if-check:
if(!num) { var num = 1000; }
Никогда не должен запускаться, поскольку num
уже определен, верно? Но это неправильная интуиция. Фактически он печатает 1000.
Давайте посмотрим на функцию getNum()
поближе, чтобы увидеть, что происходит под капотом:
- Область видимости переменной
num
вgetNum
методе - это всяgetNum
функция (а не только оператор if). - Помните, что все объявления JavaScript поднимаются в верх области. Это относится и к переменной
num
.
Учитывая, что подъем происходит, метод getNum
на самом деле ведет себя так:
Теперь становится очевидным, почему !num
возвращает true
при проверке if. Переменная num
равна undefined
, потому что она поднята на вершину области видимости функции getNum
.
Чтобы преодолеть это, используйте let
вместо var
.
В JavaScript let
(и const
) поднимаются, поэтому их невозможно использовать, пока им не будет присвоено значение.
Давайте заменим var
на let
в приведенном выше примере и посмотрим, что произойдет:
Выход:
Your number is 1
Теперь все работает так, как вы ожидали.
Вы можете возразить, что это происходит потому, что let
не поднимается. Но это не так. Объявления let
и const
также подняты. Разница в том, что подъем let
или const
не присваивает undefined
переменной.
Итак, используя let
или const
вот так:
console.log(name); let name = "Matt"; console.log(name); const name = "Matt";
Выдает ошибку. Но используя var
:
console.log(name); var name = "Matt";
Печатает undefined
, как вы уже видели.
Как правило, вам следует избегать использования var
и использовать вместо него let
или const
, чтобы избежать путаницы, связанной с подъемом.
Подъем функций в JavaScript
Теперь вы знаете, что такое подъем, и видели примеры его применения к переменным. Давайте тогда посмотрим, что означает подъем при работе с функциями в JavaScript.
Функции поднимаются как единое целое
В отличие от переменных, объявление функции поднимает всю функцию в верхнюю часть области видимости. Это означает, что вы можете вызывать функцию независимо от того, где вы ее определили в области видимости.
Например, давайте вызовем функцию перед ее определением:
sayHello(); function sayHello(){ console.log("Hello world!"); }
Выход:
Hello world!
Работает как шарм.
Выражения функций поднимаются как переменные
В предыдущем разделе вы видели, как функция поднимается в верхнюю часть контекста.
Но функциональные выражения не так поднимаются. Вместо этого они поднимаются, как переменные, которые вы видели ранее.
Посмотрим на пример:
hello(); var hello = function() { console.log("Hello world!"); }
Выход:
error: Uncaught TypeError: hello is not a function
Это происходит потому, что эта функция еще не назначена hello
, когда мы ее вызываем. Если вы зарегистрируете hello
как переменную вместо того, чтобы вызывать ее как функцию, вы получите undefined
:
console.log(hello); var hello = function() { console.log("Hello world!"); }
Выход:
undefined
Это связано с тем, что выражение функции поднимается в верхнюю часть области видимости, как обычная переменная.
Заключение
Подъем в JavaScript означает, что любые объявления перемещаются в верхнюю часть области видимости.
- Когда переменная поднимается, ей присваивается
undefined
. - Но когда функция поднята, вы можете вызвать ее перед определением:
sayHi(); function sayHi() { console.log("Hello world!"); } // ---> Hello world!
Подъем всегда происходит под капотом до выполнения любого кода. Это потому, что JavaScript хочет найти все переменные и функции, чтобы зарезервировать для них память.
Чтобы избежать путаницы, связанной с подъемом переменных, рекомендуется использовать let
или const
вместо var
.
Спасибо за прочтение. Надеюсь, вам понравилось.
Удачного кодирования!