Что это: механизм, при котором объявления переменных и функций логически перемещаются в начало их текущей области видимости во время фазы компиляции. При этом: объявления функций (function declaration) поднимаются полностью — можно вызывать до места объявления;объявления через var поднимаются, но инициализация выполняется в месте присвоения — до присвоения значение undefined.let/const и class объявляются тоже «логически поднятыми», но доступны в temporal dead zone (TDZ) до фактической инициализации.Проблемы: неожиданные undefined, вызовы неинициализированных значений, ошибки в логике.
Способы исправления:
ES6: использовать let/const вместо var (устраняет нежелательное поведение).ES6: объявлять функции как const/let-значения (function expressions / arrow functions) — они не поднимаются как function declaration.Общая практика: объявлять переменные и функции до их использования (top-down code).ES5 (если нужно ограничить область видимости): использовать IIFE, чтобы контролировать видимость и инициализацию.
Closure (замыкание)
Что это: функция вместе с «захваченными» внешними переменными из лексической области видимости, даже когда внешняя функция уже завершила выполнение. Замыкание хранит ссылки на те переменные, к которым есть доступ.Пример полезного применения: фабрика функций, приватные счётчики, сохранение состояния.
Типичный подвох + исправления:
Проблема: цикл с var и отложенными колбэками — все колбэки видят одно и то же финальное значение переменной. ES5-исправление: IIFE для захвата текущего значения: for (var i = 0; i < 3; i++) { (function(j) { setTimeout(function() { console.log(j); }, 100); })(i); }ES6-исправление: использовать let в заголовке цикла — для каждой итерации создаётся своя привязка: for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); }Альтернатива: фабрика функций: function makeLogger(x) { return function() { console.log(x); }; }
Lexical scope (лексическая область видимости)
Что это: правило, по которому принадлежность переменной к области видимости определяется по месту объявления в исходном коде (а не по месту вызова). Вложенные функции имеют доступ к переменным внешних функций, и это определяется статически.Отличие от динамической области видимости: при лексической — поиск переменных идёт по структуре кода вверх; при динамической — по стеку вызовов (JS использует лексическую).
Примеры и советы:
Лексическая область — основа замыканий: внутренняя функция всегда «видит» внешние переменные, которые были в момент её объявления. function outer(x) { let y = x + 1; function inner() { return y; // лексически связана с outer } return inner; }Чтобы избежать ошибок с областью видимости: ES6: предпочитать let/const для блочной области видимости.ES5: при необходимости создавать новый scope через IIFE.Явно передавать значения в функции вместо опоры на внешние переменные, если нужно чистое поведение.
Коротко — практические рекомендации
Используйте let/const (ES6) вместо var.Объявляйте функции/переменные до использования, когда это возможно.Для исправления проблем с замыканиями в ES5 используйте IIFE или фабрики функций; в ES6 — let в циклах и стрелочные функции, если нужен лексический this.Понимайте, что лексическая область видимости — причина замыканий и ключ к прогнозируемому поведению кода.
Hoisting (поднятие)
Что это: механизм, при котором объявления переменных и функций логически перемещаются в начало их текущей области видимости во время фазы компиляции. При этом:объявления функций (function declaration) поднимаются полностью — можно вызывать до места объявления;объявления через var поднимаются, но инициализация выполняется в месте присвоения — до присвоения значение undefined.let/const и class объявляются тоже «логически поднятыми», но доступны в temporal dead zone (TDZ) до фактической инициализации.Проблемы: неожиданные undefined, вызовы неинициализированных значений, ошибки в логике.
Способы исправления:
ES6: использовать let/const вместо var (устраняет нежелательное поведение).ES6: объявлять функции как const/let-значения (function expressions / arrow functions) — они не поднимаются как function declaration.Общая практика: объявлять переменные и функции до их использования (top-down code).ES5 (если нужно ограничить область видимости): использовать IIFE, чтобы контролировать видимость и инициализацию.Closure (замыкание)
Что это: функция вместе с «захваченными» внешними переменными из лексической области видимости, даже когда внешняя функция уже завершила выполнение. Замыкание хранит ссылки на те переменные, к которым есть доступ.Пример полезного применения: фабрика функций, приватные счётчики, сохранение состояния.Типичный подвох + исправления:
Проблема: цикл с var и отложенными колбэками — все колбэки видят одно и то же финальное значение переменной.ES5-исправление: IIFE для захвата текущего значения:
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() { console.log(j); }, 100);
})(i);
}ES6-исправление: использовать let в заголовке цикла — для каждой итерации создаётся своя привязка:
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}Альтернатива: фабрика функций:
function makeLogger(x) { return function() { console.log(x); }; }
Lexical scope (лексическая область видимости)
Что это: правило, по которому принадлежность переменной к области видимости определяется по месту объявления в исходном коде (а не по месту вызова). Вложенные функции имеют доступ к переменным внешних функций, и это определяется статически.Отличие от динамической области видимости: при лексической — поиск переменных идёт по структуре кода вверх; при динамической — по стеку вызовов (JS использует лексическую).Примеры и советы:
Лексическая область — основа замыканий: внутренняя функция всегда «видит» внешние переменные, которые были в момент её объявления.function outer(x) {
let y = x + 1;
function inner() {
return y; // лексически связана с outer
}
return inner;
}Чтобы избежать ошибок с областью видимости:
ES6: предпочитать let/const для блочной области видимости.ES5: при необходимости создавать новый scope через IIFE.Явно передавать значения в функции вместо опоры на внешние переменные, если нужно чистое поведение.
Коротко — практические рекомендации
Используйте let/const (ES6) вместо var.Объявляйте функции/переменные до использования, когда это возможно.Для исправления проблем с замыканиями в ES5 используйте IIFE или фабрики функций; в ES6 — let в циклах и стрелочные функции, если нужен лексический this.Понимайте, что лексическая область видимости — причина замыканий и ключ к прогнозируемому поведению кода.