Подъем в javascript — это процесс, в котором интерпретатор перемещает переменные, функции и объявление класса в верхнюю часть их области действия до выполнения кода.

Не до конца понял? Нет проблем, позвольте мне объяснить.

Простыми словами, подъем позволяет нам безопасно использовать переменные/функции в коде до их объявления, перемещая их в верхнюю часть их области видимости, но не рекомендуется использовать их до их объявления, так как это может привести к ошибкам.

Подъем выполняется на этапе создания глобального контекста выполнения.

В этой статье мы узнаем обо всех типах подъема один за другим.

Переменный подъем:

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

Объявление переменной с помощью var:

Давайте разберемся, как работает подъем, когда переменная объявляется с помощью var с помощью блока кода.

1. console.log(x)
2. var x;
3. x = 2;
4. console.log(x)

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

Перед выполнением кода интерпретатор сканирует код и ищет все объявления переменных, доступные в файле, и перемещает их в верхнюю часть своей области. В этом случае интерпретатор переместит строку № 2 поверх глобальной области видимости, поскольку мы объявляем ее в главном дереве.

Вот как javascript будет интерпретировать это из-за подъема:

1. var x; // Declaration 
2. console.log(x) // Returns 'undefined' instead of 2
3. x = 2; // Initialization
4. console.log(x) // Returns 2 as x is initialized with 2 now.

В строке № 1 объявлено x, в строке № 2 он будет логundefined в консоли, потому что x объявлен с использованием var, поэтому он имеет undefined в качестве инициализации по умолчанию, в строке № 3 x инициализируется своим фактическим значением 2 и в строке № 4 он будет зарегистрирован в консоли по фактическому значению 4 .

То же самое произойдет, если мы объявим и инициализируем переменную одновременно.

1. console.log(x) // Returns 'undefined' instead of 2
2. var x = 2; // Initialization
3. console.log(x) // Returns 2 as x is initialized with 2 now.

Примечание. Если мы совсем забыли объявить переменную, она выдаст исключение throwReferenceError.

Объявление переменной с помощью let и const:

Переменные, объявленные с использованием let and const, также поднимаются, но не инициализируются значением по умолчанию, поэтому доступ к этим переменным до объявления вызовет исключение ReferenceError, поскольку переменная не инициализирована.

1. console.log(x) // This will throw ReferenceError exception
2. let x = 2; // Initialization
3. console.log(x) // Returns 2 as x is initialized with 2 now.

Функция подъема:

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

1. console.log(sum(2,3));
2. function sum(firstNum, secondNum) {
3.   return firstNum + secondNum;
4. }
 // 5 will be the output of this code

Без подъема мы должны позаботиться о порядке использования и объявления, благодаря подъему мы можем игнорировать его порядок.

Давайте посмотрим на другом примере, как подъем работает с функциональными выражениями.

1. console.log(getRectArea(2,3));
2. let getRectArea = function(width, height) {
3.   return width * height;
4. };
// This code block will result in ReferenceError exception.

Пришло время напомнить о моменте, который мы обсуждали ранее в этой статье: javascript hoist только декларация, а не инициализация.

Давайте посмотрим, что происходит, когда интерпретатор сканирует код перед выполнением:

При сканировании, когда дело доходит до строки № 2, он увидит объявление и переместит его в верхнюю часть области, и в этом случае вся строка не будет перемещаться вверх, а просто переместится часть объявления let getRectArea;, вот и все. Просто чтобы было ясно, что назначение функции переменной getRectArea является частью процесса инициализации.

Когда строка #1 выполняется, интерпретатор найдет вызов функции, хотя он не знает о каком-либо объявлении функции, поэтому это приведет к исключению.

Функция и выражение класса работают почти по одному шаблону, поэтому мы можем сказать, что функции и выражения класса не поднимаются в javascript.

Подъем класса:

В javascript мы можем объявить класс, используя ключевое слово class вместе с именем класса.

1. class Student {
2.   constructor(id, name, subject) {
3.     this.id = id;
4.     this.name = name;
5.     this.subject = subject;
6.   }
7. }

Этот метод называется объявлением класса.

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

Заключение:

Я бы сказал, что в javascript имеет значение только порядок выполнения блока кода, а не порядок, в котором он написан.

Мы можем использовать переменные (объявленные только с помощью var ) и функции перед их объявлением, но это не очень хороший подход, поэтому попробуйте объявить все свои переменные, а затем получить к ним доступ.