Кратко
Область видимости (scope) определяет, где переменная доступна. Global scope — доступна везде. Function scope — только внутри функции. Block scope (let/const) — только внутри { }. Lexical scope — вложенная функция видит переменные внешней функции. Closure — когда функция «запоминает» внешние переменные даже после завершения внешней функции.
Подробно
Что такое область видимости?
Область видимости (scope) — это контекст, в котором переменная объявлена и доступна. JavaScript ищет переменные «сверху вниз» по цепочке областей видимости.
Три типа scope:
- Global scope:
const name = 'Анна'; // доступна везде
- Function scope:
function greet() { const message = 'Привет'; // только внутри greet } // message недоступна здесь
- Block scope:
if (true) { let x = 10; // только внутри if const y = 20; // только внутри if } // x и y недоступны здесь
var vs let/const:
- var создаёт function scope (вне блоков!)
- let/const создают block scope
Lexical scope: Вложенная функция видит переменные ВСЕХ внешних функций:
function outer() { const a = 1; function inner() { const b = 2; console.log(a + b); // 3 — видит 'a' из outer } inner(); }
Замыкание (Closure): Функция + ссылка на внешние переменные.
function createCounter() { let count = 0; return function() { count++; return count; }; }
const counter = createCounter(); counter(); // 1 counter(); // 2 counter(); // 3
Счётчик count «замкнут» внутри функции. Даже после завершения createCounter, возвращённая функция помнит count.
Цепочка областей видимости (Scope Chain): Когда JavaScript ищет переменную, он поднимается по вложенности: inner → outer → global. Если не нашёл — ReferenceError.
Ментальная модель
Область видимости — как комната в доме. Вы видите то, что в вашей комнате (local scope) и то, что в коридоре (outer scope). Но не видите то, что в другой комнате (другая function scope). Closure — как комната с окном: даже когда вы уходите из коридора, вы всё ещё видите через окно то, что там было.
Примеры
**Самый простой:**
const global = 'я глобальная';
function test() {
const local = 'я локальная';
console.log(global); // видит глобальную
console.log(local); // видит локальную
}
test();
console.log(global); // OK
// console.log(local); // ReferenceError!Global scope доступна везде. Function scope — только внутри функции.
**Простой:**
function createMultiplier(factor) {
return function(number) {
return number * factor; // factor «замкнута»
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15Каждая функция createMultiplier создаёт своё замыкание со своим factor.
**Реальный пример:**
function createBankAccount(initialBalance) {
let balance = initialBalance;
return {
deposit(amount) {
balance += amount;
return balance;
},
withdraw(amount) {
if (amount > balance) return 'Недостаточно средств';
balance -= amount;
return balance;
},
getBalance() {
return balance;
}
};
}
const account = createBankAccount(1000);
console.log(account.deposit(500)); // 1500
console.log(account.withdraw(200)); // 1300
console.log(account.getBalance()); // 1300
// account.balance — undefined (приватная переменная!)Balance защищён замыканием — его нельзя изменить напрямую.
Частые ошибки
**Неправильно:** Путать var и let/const в циклах
**Почему:** var создаёт одну переменную на всю функцию. Все итерации цикла видят одну и ту же переменную.
**Правильно:** Используйте let в циклах — каждая итерация получает свою переменную.
**Неправильно:** Думать, что closure — это копия переменной
**Почему:** Closure хранит ССЫЛКУ на переменную, а не копию. Изменения видны.
**Правильно:** Closure — функция + ссылка на внешние переменные.
**Неправильно:** Забывать, что цикл с var создаёт одну переменную
**Почему:** for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i)); } выведет 3, 3, 3.
**Правильно:** Используйте let: for (let i = 0...) — каждая итерация получает свою i.
Важно запомнить
- Global scope — доступна везде
- Function scope — только внутри функции
- Block scope (let/const) — только внутри { }
- Lexical scope — вложенная функция видит внешние переменные
- Closure — функция + ссылка на внешние переменные
- var не имеет block scope!
Связь
Назад: Вы знаете функции и переменные (J0-J26) — теперь вы понимаете, где они «живут».
Вперёд: Следующий урок (JI2) — глобальный объект window и его свойства.