Область видимости
Область видимости — часть кода, где переменная доступна.
Виды областей
- Глобальная — весь скрипт
- Функциональная — внутри функции
- Блочная — внутри
{}(дляletиconst)
Глобальная область
var globalVar = 1;
let globalLet = 2;
function test() {
console.log(globalVar); // 1
console.log(globalLet); // 2
}
Глобальные переменные — плохая практика в больших проектах.
Функциональная
function test() {
const x = 1;
console.log(x); // 1
}
console.log(x); // ошибка
var создаёт переменную в функциональной области:
function test() {
if (true) {
var x = 1;
}
console.log(x); // 1, хотя x в if
}
Блочная
let и const — только внутри блока:
if (true) {
let x = 1;
const y = 2;
}
console.log(x); // ошибка
Блок — {} в if, for, while, просто {}.
Вложенные области
Внутренняя видит внешнюю:
const a = 1;
function outer() {
const b = 2;
function inner() {
const c = 3;
console.log(a, b, c); // 1 2 3
}
inner();
// console.log(c); // ошибка
}
Внешняя не видит внутреннюю.
Цепочка областей
При обращении к переменной JavaScript ищет её:
- В текущей области
- В родительской
- В родительской родительской
- В глобальной
- Если не находит —
ReferenceError
Затенение
Внутренняя переменная скрывает внешнюю:
const name = 'Алиса';
function greet() {
const name = 'Боб';
console.log(name); // 'Боб'
}
greet();
console.log(name); // 'Алиса'
Утечка глобальных
Без let, const, var — переменная становится глобальной:
function test() {
x = 1; // глобальная
}
test();
console.log(x); // 1
В strict mode — ошибка.
Модули
В ES-модулях верхний уровень — не глобальная область. Переменные модуля не попадают в window:
// module.js
const x = 1; // не глобальная
var в цикле
Классическая проблема:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 3, 3, 3 — все видят одну i
С let:
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 0, 1, 2 — у каждой итерации своя i
let в for создаёт новую переменную для каждой итерации.
IIFE для изоляции
(function() {
const secret = 'внутри';
// secret не видна снаружи
})();
В модулях не нужно.
Замыкания
Внутренняя функция сохраняет доступ к переменным внешней даже после её завершения:
function counter() {
let count = 0;
return () => ++count;
}
const next = counter();
next(); // 1
next(); // 2
Подробнее — в следующих уроках.
Итоги
- Глобальная, функциональная, блочная
letиconst— блочныеvar— функциональная- Внутренняя видит внешнюю
- Затенение перекрывает внешнее
- Без объявления — утечка в глобальную