JavaScript: подъем

Прежде чем мы разберемся с подъемом, давайте вкратце познакомимся с контекстом выполнения JavaScript.

Контекст выполнения

Проще говоря, контекст выполнения - это среда, в которой код JavaScript оценивается и выполняется.

Контекст выполнения создается в два этапа:

  1. Этап создания: На этом этапе создается this, глобальный объект (в случае глобального контекста выполнения) и лексическая среда (отображение идентификатора и переменной). На этом этапе он устанавливает объем памяти для переменных и функций.
  2. Этап выполнения. На этом этапе происходит присвоение переменных и выполнение кода.

Теперь давайте взглянем на фрагмент кода:

var a = 20;
console.log(a);
Output:
20

Давайте изменим приведенные выше строки кода на это:

console.log(a);
console.log(b);
var a = 20;
Output:
undefined
ReferenceError: b is not defined

Итак, почему console.log(a) в приведенном выше фрагменте кода - это undefined и почему не выдает ошибку, что a не определен, хотя мы пытаемся получить к нему доступ еще до того, как он объявлен?

Это из-за подъема.

Подъем: процесс настройки пространства памяти для переменных и функций на этапе создания контекста выполнения.

Даже до начала выполнения кода движок JavaScript устанавливает пространство оперативной памяти для всех переменных и функций, используемых в коде на этапе создания (т. Е. Объявления переменных и объявления функций хранятся в памяти), тогда как присвоение переменной происходит на этапе выполнения (когда код выполняется).

Итак, для приведенного выше фрагмента кода, когда код выполняется (фаза выполнения), переменная a уже находится в памяти, и по умолчанию переменные var имеют значение undefined. Поскольку наш console.log(a) находится перед присвоением a, он отображает undefined.

Вот что происходит с переменными var. Теперь посмотрим, как работают let и const.

let и const:

console.log(a);
let a = 20;
output:
ReferenceError: Cannot access 'a' before initialization

Это не означает, что let и const не поднимаются. Но в отличие от var, который инициализируется значением undefined, let и const не инициализируются ничем (на этапе создания) до тех пор, пока мы не встретим объявление переменной на этапе выполнения. Этот промежуток от создания переменной в памяти до момента, когда мы обнаруживаем объявление переменной на этапе выполнения, называется Временная мертвая зона, и в течение этого периода доступ к переменным невозможен.

let a;
const b = 10;
console.log(a);
console.log(b);
a = 50;
output:
undefined
10

Примечание. Мы не можем просто объявить переменную const и не присвоить ей значение. т.е. const b; не допускается. Кинул бы SyntaxError: Missing initializer in const declaration.

Теперь, когда мы знаем, как подъем работает для переменных (var, let и const), давайте взглянем на подъем функции.

Функция:

Это работает аналогично подъему переменных. Однако давайте рассмотрим два способа определения функций в javascript и то, как подъем работает в обоих случаях:

  1. Объявления функций
  2. Функциональные выражения

1. Объявления функций

display();
function display() {
  console.log("Hello World!");
}
output:
Hello World!

Мы знаем, что переменные и функции помещаются в память (на этапе создания контекста выполнения) еще до начала выполнения кода. Здесь полная функция помещается в память на этапе создания. Итак, когда выполнение начинается, и мы сталкиваемся с вызовом функции, функция выполняется.

2. Функциональные выражения

display();
var display = function() {
  console.log("Hello World!");
}
output:
TypeError: display is not a function

Итак, вы уже знаете упражнение. JavaScript обнаруживает display переменную на этапе создания, он сохраняет переменную в памяти, и, поскольку это var, отображение инициализируется на undefined. Позже, на этапе выполнения, когда мы сталкиваемся с вызовом функции display(), в этот момент display - это просто переменная в памяти. Итак, получаем display is not a function ошибку.

Если мы разместим вызов функции после присвоения функции переменной, на выходе будет Hello World!.

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