Что такое hoisting(всплытие) в JavaScript? Flashcards
Что такое hoisting(всплытие) в JavaScript?
Поднятие или hoisting — это механизм в JavaScript, в котором переменные и объявления функций, передвигаются вверх своей области видимости перед тем, как код будет выполнен.
Подниманием называется поведение, при котором JavaScript перемещает объявления переменных, функций и классов в начало области видимости на этапе компиляции. Иногда это может привести к неожиданным результатам, особенно при использовании выражений var, let, const или функций.
Подъем применяется к объявлениям переменных и функций.
Инициализации не запускаются, это всего лишь объявления.
Переменные «var» поднимаются с неопределённым значением, в то время как «let» и «const» поднимаются, но остаются в «мёртвой зоне» до инициализации.
Временная мёртвая зона (TDZ)является важным понятием в подъёме переменных в JavaScript. Она относится к периоду между входом в область видимости (например, функцию или блок) и фактической инициализацией переменной, объявленной с помощью let или const. В течение этого времени любая ссылка на переменную до её инициализации приведёт к ошибке ReferenceError.
Как работает TDZ?
- Переменные, объявленные с помощью let и const, поднимаются в начало области видимости, но не инициализируются до тех пор, пока не будет достигнута строка их объявления.
- Любая попытка получить доступ к этим переменным до их объявления приведет к ошибке.
- TDZ существует только для переменных, объявленных с помощью let и const. Переменные, объявленные с помощью var, не имеют этой проблемы, так как они поднимаются и инициализируются значением undefined.
hello(); // TypeError: hello is not a function
var hello = function() {
console.log(“Hi!”);
};
Переменная hello поднимается в верхнюю часть области видимости, но не инициализируется до тех пор, пока не будет достигнута строка присваивания, поскольку она содержит функциональное выражение. Таким образом, вызов hello() до её инициализации приводит к ошибке TypeError.
- Переменный подъем с помощью var
Когда вы используете var для объявления переменной, объявление поднимается наверх, но его значение не присваивается до тех пор, пока выполнение кода не достигнет инициализации переменной. Это приводит к тому, что на этапе поднятия переменной присваивается неопределённое значение.
console.log(a); // undefined
var a = 5;
Объявление var a перемещается в начало, но a инициализируется значением undefined. Следовательно, при выводе в журнал будет отображаться значение undefined. - Переменный подъем с помощью let и const
В отличие от var, let и const также поднимаются, но они остаются в временной мёртвой зоне (TDZ) с начала блока до тех пор, пока не встретится их объявление. При обращении к ним до их объявления будет выдана ошибка ReferenceError.
console.log(b); // ReferenceError: Cannot access ‘b’ before initialization
let b = 10;
Переменная поднимается, но находится в временной мёртвой зоне (TDZ) до тех пор, пока не будет выполнена строка объявления. - Объявление функции Подъема
Объявления функций поднимаются вместе с их именами и телом функции. Это означает, что функцию можно вызвать до её определения в коде.
greet(); // “Hello, world!”
function greet() {
console.log(“Hello, world!”);
}
Объявление функции поднимается вверх, и всё определение функции становится доступным до того, как оно будет использовано в коде. - Подъем выражения функции
Функциональные выражения обрабатываются как объявления переменных. Сама переменная поднимается, но функциональное выражение не присваивается до выполнения строки. Это означает, что вызов функции до её присвоения приведёт к ошибке.
hello(); // TypeError: hello is not a function
var hello = function() {
console.log(“Hi!”);
};
Переменная hello поднимается, но, поскольку это функциональное выражение, она не инициализируется до выполнения строки. - Подъем с функциями let и const в
Переменные, объявленные с помощью let и const внутри функции, поднимаются в начало области видимости функции, но остаются в TDZ. Это предотвращает доступ к ним до их инициализации.
function test() {
console.log(x); // ReferenceError: Cannot access ‘x’ before initialization
let x = 50;
}
test();
Переменная x перемещается внутрь функции, но не может быть доступна до строки её объявления из-за TDZ. - Подъем с помощью классов
Классы поднимаются наверх, но к ним нельзя получить доступ до их объявления, что приводит к ошибке ReferenceError.
const obj = new MyClass(); // ReferenceError
class MyClass {
constructor() {
this.name = “Example”;
}
}
Хотя класс MyClass поднимается, к нему нельзя получить доступ до его объявления из-за TDZ, поэтому в коде возникает ошибка ReferenceError. - Повторное объявление переменных с помощью var
С помощью var можно повторно объявить переменную в той же области видимости. Это уникальное поведение по сравнению с let и const.
var a = 10;
var a = 20; // No error
console.log(a); // 20
При использовании var второе объявление перезаписывает первое без выдачи ошибки. - Доступ к переменным, объявленным позже в циклах
При использовании var в циклах переменная цикла переносится в функцию или глобальную область видимости, что может привести к неожиданному поведению. Если вы используете let, переменная имеет область видимости блока и ведёт себя ожидаемым образом.
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // 3, 3, 3
}, 100);
}
Переменная i поднимается, и все функции setTimeout используют одну и ту же ссылку на i, что приводит к значению 3 после завершения цикла. - Использование поднятых функций с параметрами
Функции могут быть подняты вместе со своими параметрами, но любые параметры, передаваемые в функцию, по-прежнему определяются вызовом, а не поднятием.
test(10); // 10
function test(num) {
console.log(num);
}
Вся функция, включая её параметры, поднимается и становится доступной для использования до того, как функция будет объявлена в коде. - Подъем во вложенных функциях
Поднятие переменных работает и во вложенных функциях. Переменные, объявленные с помощью var внутри функции, поднимаются в начало области видимости этой функции.
function outer() {
console.log(a); // undefined
var a = 5;
function inner() {
console.log(b); // undefined
var b = 10;
}
inner();
}
outer();
И a, и b поднимаются в пределах своих областей видимости (внешней и внутренней функций), но их значения не устанавливаются до тех пор, пока выполнение кода не достигнет строк инициализации.