Подъем в 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
) и функции перед их объявлением, но это не очень хороший подход, поэтому попробуйте объявить все свои переменные, а затем получить к ним доступ.