Замыкание - одно из мощных выразительных средств javascript, которым часто пренебрегают, и даже не советуют употреблять.
Действительно, замыкания могут приводить к проблемам. Но на самом деле они очень удобны, просто нужно понимать, что реально происходит.
Простое описание
Если говорить просто, то замыкание - это внутренняя функция. Ведь javascript разрешает создавать функции по ходу выполнения скрипта. И эти функции имеют доступ к переменным внешней функции.
В этом примере создается внутренняя функция func, изнутри которой доступны как локальные переменные, так и переменные внешней функции outer:
01
function outer() {
02
var outerVar;
03
04
var func = function() {
05
var innerVar
06
...
07
x = innerVar + outerVar
08
}
09
return func
10
}
Когда заканчивает работать функция outer, внутренняя функция func остается жить, ее можно запускать в другом месте кода.
Получается, что при запуске func используется переменная уже отработавшей функции outer, т.е самим фактом своего существования, func замыкает на себя переменные внешней функции (а точнее - всех внешних функций).
Наиболее часто замыкания применяются для назначения функций-обработчиков событий:
1
function addHideHandler(sourceId, targetId) {
2
var sourceNode = document.getElementById(sourceId)
3
var handler = function() {
4
var targetNode = document.getElementById(targetId)
5
targetNode.style .display = ‘none’
6
}
7
sourceNode.onclick = handler
8
}
Эта функция принимает два ID элементов HTML и ставит первому элементу обработчик onclick, который прячет второй элемент.
Т.е,
// при клике на элемент с ID="clickToHide"
// будет спрятан элемент с ID="info"
addHideHandler("clickToHide", "info")
Здесь динамически созданный обработчик события handler использует targetId из внешней функции для доступа к элементу.
Подробное описание
.. Если Вы хотите углубиться поглубже и разбираться подольше..
..На самом деле происходящее в интерпретаторе Javascript гораздо сложнее и содержит куда больше деталей, чем здесь описано...
..Но чтобы понять и использовать замыкания, достаточно понять внутренний механизм работы функций, хотя бы и в таком, местами упрощенном виде...
[[scope]]
Каждое выполнение функции хранит все переменные в специальном объекте с кодовым именем [[scope]], который нельзя получить в явном виде, но он есть .
Каждый вызов var... - всего лишь создает новое свойство этого объекта, а любое упоминание переменной - первым делом ищется в свойствах этого объекта.
Такова внутренняя структура "области видимости" - это обыкновенный объект. Все изменения локальных переменных являются изменениями свойств этого неявного объекта.
Обычно после того, как функция закончила выполнение, ее область видимости [[scope]], т.е весь набор локальных переменных убивается.
Общий поток выполнения выглядит так:
01
// функция для примера
02
function sum(x,y) {
03
// неявно создался объект [[scope]]
04
...
05
// в [[scope]] записалось свойство z
06
var z
07
// нашли переменную в [[scope]], [[scope]].z = x+y
08
z = x+y
09
// нашли переменную в [[scope]], return [[scope]].z
10
return z
11
12
// функция закончилась,
13
// [[scope]] никому больше не нужен и умирает вместе с z
14
}
Кстати, для кода вне функции(и вообще глобальных переменных) роль объекта-контейнера [[scope]] выполняет объект window.
Присоединяйтесь — мы покажем вам много интересного
Присоединяйтесь к ОК, чтобы подписаться на группу и комментировать публикации.
Нет комментариев