В этом руководстве вы узнаете о поднятии переменных и объявлений функций в JavaScript и о том, как это работает внутри.
Когда механизм JavaScript выполняет код JavaScript, он создает глобальный контекст выполнения. Глобальный контекст выполнения состоит из двух фаз: создание и выполнение.
На этапе создания механизм JavaScript перемещает объявления переменных и функций в начало кода. Эта функция известна как поднятие или подъем в JavaScript.
Подъем переменных
Подъем переменных означает, что движок JavaScript перемещает объявления переменных в начало скрипта. Например, в следующем примере объявляется переменная counter
и инициализируется ее значение равным 1
:
console.log(counter); // undefined var counter = 1;
В этом примере мы ссылаемся на переменную счетчика перед объявлением.
Однако первая строка кода не вызывает ошибки. Причина в том, что движок JavaScript перемещает объявление переменной в начало скрипта.
Технически код на этапе выполнения выглядит следующим образом:
var counter; console.log(counter); // undefined counter = 1;
На этапе создания глобального контекста выполнения механизм JavaScript помещает переменную counter
в память и инициализирует ее значение равным undefined
.
Ключевое слово let
Следующее объявляет переменную counter
с помощью ключевого слова let
:
console.log(counter); let counter = 1;
JavaScript выдает следующую ошибку:
"ReferenceError: Cannot access 'counter' before initialization
Сообщение об ошибке объясняет, что переменная счетчика уже находится в куче памяти. Однако он не был инициализирован.
За кулисами движок JavaScript поднимает объявления переменных, в которых используется ключевое слово let
. Однако он не инициализирует let
.
Обратите внимание, что если вы обращаетесь к несуществующей переменной, JavaScript выдаст другую ошибку:
console.log(alien); let counter = 1;
Вот ошибка:
"ReferenceError: alien is not defined
Подъем функций
Как и переменные, движок JavaScript также поднимает объявления функций. Это означает, что движок JavaScript также перемещает объявления функций в начало скрипта.
Например:
let x = 20, y = 10; let result = add(x, y); console.log(result); function add(a, b) { return a + b; }
В этом примере мы вызвали функцию add()
перед ее определением. Приведенный выше код эквивалентен следующему:
function add(a, b){ return a + b; } let x = 20, y = 10; let result = add(x,y); console.log(result);
На этапе создания контекста выполнения механизм JavaScript помещает объявление функции add()
в динамическую память. Чтобы быть точным, механизм JavaScript создает объект типа Function
и ссылку на функцию с именем add
, которая ссылается на объект функции.
Функциональные выражения
В следующем примере add
из обычной функции заменяется выражением функции:
let x = 20, y = 10; let result = add(x,y); console.log(result); var add = function(x, y) { return x + y; }
Если вы выполните код, произойдет следующая ошибка:
"TypeError: add is not a function
На этапе создания глобального контекста выполнения механизм JavaScript создает переменную add
в памяти и инициализирует ее значение равным undefined
.
При выполнении следующего кода add
не undefined
, следовательно, это не функция:
let result = add(x,y);
Переменная add
назначается анонимной функции только на этапе выполнения глобального контекста выполнения.
Стрелочные функции
В следующем примере выражение add
функции заменяется функцией стрелки:
let x = 20, y = 10; let result = add(x,y); console.log(result); var add = (x, y) => x + y;
Код также выдает ту же ошибку, что и пример функционального выражения, потому что стрелочные функции являются синтаксическим сахаром для определения функциональных выражений.
"TypeError: add is not a function
Подобно выражениям функций, функции со стрелками не поднимаются.
Заключение
- Поднятие в JavaScript происходит на этапе создания контекста выполнения, который перемещает объявления переменных и функций в начало сценария.
- Движок JavaScript поднимает переменные, объявленные с помощью ключевого слова
let
, но не инициализирует их как переменные, объявленные с помощью ключевого словаvar
. - Движок JavaScript не поднимает функциональные выражения и стрелочные функции.