Поднятие в JS (Hoisting в Javascript + 3 примера)
В этой статье мы с вами разберемся как что такое, и как работает поднятие (Hoisting) в Javascript. Эта одна из базовых тем в ванильном JS и вы однозначно наткнетесь на нее в одном из интервью при устройстве на работу.
Поднятие в JS - возможность получать доступ к функциям и переменным до того, как они были созданы. Это механизм относится только к объявлению функций и переменных.
Поднятие в JS (пример с функцией)
Для нашего примера создадим функцию letsGo и попробуем ее вызвать до ее создания.
1// Вызываем функцию letsGo до ее создания2letsGo();34function letsGo() {5 console.log('Go!!');6}78// В консоли получаем9// Go!!
Наша функция запускается, и мы получаем строку "Go!!" в нашей консоли. Это происходит, так как срабатывает мехнаизм "поднятие" в Javascript.
То есть, "под капотом" компилятор JS "поднимает" все строчки, где объявляются функции на самый верх.
Ваглядит это так:
1// 1. "Под капотом" - компилятор JS поднимает объявление нашей функции на самый верх:2// function letsGo() {3// console.log('Go!!');4// }56letsGo();78function letsGo() {9 console.log('Go!!');10}
Таким образом, мы получаем возможность запускать нашу функцию letsGo - до ее объявления.
Теперь, давайте немного расширим наш пример и создадим еще одну функцию add.
1// Запускаем функцию letsGo2letsGo();34// Объявляем функцию letsGo5function letsGo() {6 console.log('Go!!');78 // Запускаем функцию add9 add(5, 3);10}1112// Объявляем функцию add13function add(a, b) {14 return a + b;15}1617// В консоли получаем:18// Go!!19// 8
Как мы видим, функция add - принимает 2 значения и возвращает их сумму. Мы также запускаем функцию add до ее создания - внутри нашей первой функции letsGo.
Мы видим, что наша вторая функция add также срабатывает и получаем результат сложения в консоли. То есть, опять, сработал механизм "поднятия" в JS, который поднял весь код, где объявляются функции на самый верх.
Применительно к функциям, "поднятие" работает только с объявлением функций!
Поднятие в JS не работает при использовании функциональных выражений, стрелочных функций и любых других способов создания функций...
То есть, если мы попробуем использовать функциональное выражение и запустить функцию до ее создания, то получим ошибку:
1letsGo();2// Получаем ошибку3// Uncaught ReferenceError: can't access lexical declaration 'letsGo' before initialization45// Используем функциональное выражение6const letsGo = function () {7 console.log('Go!!');8};
Если решим написать то же самое, используя стрелочную функцию, тоже получим ошибку ("поднятие" не работает):
1letsGo();2// Получаем ошибку3// Uncaught ReferenceError: can't access lexical declaration 'letsGo' before initialization45// Используем стрелочную функцию6const letsGo = () => {7 console.log('Go!!');8};
Поднятие в Javascript (пример с переменной var)
Давайте создадим переменную years, используя var и сразу попробуем вывести ее значение в лог - до ее создания.
1// Выводим значение переменной years - до ее объявления2console.log(years);3// Получаем значение undefined4// undefined5var years = 100;
Давайте, ради интереса, также выведем в лог произвольную переменную, которой у нас вообще не существует:
1// Выводим значение переменной years - до ее объявления2console.log(years);34// Выводим в лог вымышленную переменную test5console.log(test);67// Получаем значение переменной years - undefined8// undefined910// Для переменной test - получаем ошибку!11// Uncaught ReferenceError: test is not defined1213var years = 100;
То есть, когда мы выводим в лог значение переменной years, до ее создания, происходит следующее:
- Компилятор Javascript, под капотом, в самом верху, добавляет строчку с объявлением нашей переменной. То есть, инициализирует переменную со значением undefined.
1// 1. "Под капотом" - JS объявляет нашу переменную на самом верху2// var years;34// 2. Выводим значение переменной years - до ее объявления5console.log(years);67// 3. Получаем значение undefined8// undefined9var years = 100;
- В самомом конце наша переменная обновляется со значением 100
1// 1. "Под капотом" - JS объявляет нашу переменную на самом верху2// var years;34// 2. Выводим значение переменной years - до ее объявления5console.log(years);67// 3. Получаем значение undefined8// undefined9var years = 100;1011console.log(years);12// 4. Получаем обновленное значение переменной years13// 100