Область видимости и замыкания
Free PreviewВ прошлых уроках мы объявляли переменные и функции, не задумываясь о том, откуда к ним можно обращаться. На практике это важно: не каждая переменная доступна в каждом месте кода. Эту концепцию называют областью видимости (scope).
Что такое область видимости
Область видимости — это часть кода, в которой переменная существует и доступна. Если переменная объявлена в одном месте, это не значит, что к ней можно обратиться откуда угодно.
Глобальная область видимости
Переменные, объявленные вне каких-либо функций и блоков, попадают в глобальную область видимости. К ним можно обратиться из любого места программы:
const siteName = 'Санкт-Петербург'; function greet() { console.log(siteName); // доступно внутри функции } greet(); // Санкт-Петербургjs
Область видимости функции
Переменные, объявленные внутри функции, существуют только внутри неё. Снаружи они недоступны:
function calculate() { const result = 42; console.log(result); // 42 } calculate(); console.log(result); // Ошибка! result не определён снаружиjs
Блочная область видимости
let и const имеют блочную область видимости — они существуют только внутри блока {}, в котором объявлены. Это касается не только функций, но и любых блоков: if, for, while:
if (true) { let blockVar = 'я внутри блока'; console.log(blockVar); // работает } console.log(blockVar); // Ошибка! переменная не видна снаружиjs
Именно поэтому var ведёт себя иначе — у него нет блочной области видимости, только функциональная. Это одна из причин, по которым var стараются не использовать:
if (true) { var oldWay = 'я var'; } console.log(oldWay); // 'я var' — var "вытекает" из блокаjs
Вложенные области видимости
Функции могут быть вложены друг в друга. Внутренняя функция видит переменные внешней, но не наоборот:
function outer() { const message = 'снаружи'; function inner() { console.log(message); // видит переменную из внешней функции } inner(); } outer(); // 'снаружи'js
Это правило называется лексической областью видимости: функция видит переменные той области, в которой она была объявлена.
Замыкание
Замыкание (closure) — это одна из самых важных концепций в JavaScript. Звучит сложно, но идея простая: функция «запоминает» внешние переменные из своей области видимости, даже когда выполняется за её пределами.
Рассмотрим пример:
function createCounter() { let count = 0; return function() { count = count + 1; console.log(count); }; } const counter = createCounter(); counter(); // 1 counter(); // 2 counter(); // 3js
Что здесь происходит? Функция createCounter создаёт переменную count и возвращает внутреннюю функцию. Когда createCounter завершила работу, переменная count не исчезла — внутренняя функция «захватила» её и продолжает к ней обращаться.
Каждый вызов createCounter() создаёт новое замыкание со своей переменной count:
const counter1 = createCounter(); const counter2 = createCounter(); counter1(); // 1 counter1(); // 2 counter2(); // 1 — у counter2 своё собственное countjs
Замыкания используются повсюду в реальных приложениях — для создания приватных данных, фабрик функций, обработчиков событий. Это тема, к которой стоит вернуться по мере углубления в язык.
В следующем уроке поговорим об одной из самых обсуждаемых концепций JavaScript — ключевом слове this.