Знаете ли вы, что 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 letconst) поднимаются, поэтому их невозможно использовать, пока им не будет присвоено значение.

Давайте заменим 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.

Спасибо за прочтение. Надеюсь, вам понравилось.

Удачного кодирования!

Учить больше