Оригинал: «A Graphical Explanation Of Javascript Closures In A jQuery Context».
Всю неделю я работал над подробной презентацией jQuery для юзер-группы New York ColdFusion. В качестве части презентации мне хотелось обсудить прелесть замыканий в Javascript и то, как потрясающе использует их jQuery. Замыкания в Javascript могут заставить вас сильно поломать голову, особенно если вы столкнётесь с подобными определениями:
«Замыкание» — это выражение (обычно, функция), которое имеет свободные переменные и внешнюю среду, которая связывает эти переменные («замыкает» выражение).
Я хочу сказать, какого же чёрта всё это значит? Я знаю кое-что о замыканиях, но это определение ни о чём мне не говорит. Как я сказал, замыкания могут быть действительно сложны для понимания. Итак, я попытаюсь объяснить это с помощью иллюстраций, ведь, как говорят, лучше один раз увидеть, чем сто раз услышать.
Вначале, давайте взглянем на простой пример:

В этом коде мы добавляем обработчик нажатия для всех ссылок в документе. При срабатывании обработчика будет выведен индекс нажатой ссылки и их общее число. Конечно, смысл кода вторичен по сравнению с наглядностью. Что здесь действительно важно, так это структура кода. Взгляните на функции, которые были в нём определены:

Заметим, что в этом примере мы описываем три анонимных метода, каждый из которых определён в контексте своего родителя. Внешний метод определён в контексте объекта window (основываясь только на приведённом коде); средний — в контексте внешнего; и, наконец, внутренний определён в контексте среднего.
В Javascript, любой объект имеет доступ к контексту родителя. Честно говоря, механизмы, стоящие за этим, и относящиеся к разрешению имён, находятся немного за пределами моего кругозора. Как таковой, каждый метод в нашем примере имеет доступ не только к своим локальным переменным, но и к переменным из родителького контекста:

Заметьте, что во внутреннем методе, мы должны перейти к родительской области видимости, чтобы найти intLinkIndex и на две области вверх, чтобы найти переменную jLinks. Хотя это быть может и не так очевидно, переход на две области вверх следует тем же правилам - вначале, внутренний метод ищет jLinks в своей области видимости. Поскольку это не локальная переменная, он не сможет её найти. Затем, он запрашивает переменную у родительской области видимости (средний метод). Средний метод проверяет свою локальную область видимости, не находит там переменную jLinks и передаёт запрос своему родительскому контексту, внешнему методу. Итак, поскольку каждый метод имеет доступ к родительской области видимости, такой запрос легко проходит до самого верха подобной цепочки.
Итак, пока всё хорошо; теперь, давайте действительно займёмся замыканиями. Держа всё сказанное в уме, разберёмся, что происходит с этими методами:

Определяя эти анонимные методы, мы используем методы each() и click() для отделения их от родительского контекста. Куда же они помещаются? Этого мы не знаем — в целом, они помещаются в другой контекст. Конечно, из примера может показаться, что они передаются в jLinks и jThis соответственно; однако, факт в том, что как только эти методы отделяются от родительского контекста, мы не можем сказать точно, что с ними происходит. Будут ли они храниться лишь временно? Или же будут каким-то образом кэшироваться объектом window на всё время работы кода?
На эти вопросы мы ответить не можем; более того, на них не может ответить и система управления памятью браузера. И, поскольку она не знает, когда эти методы прекратят работу, она не может освободить и память, занимаемую родительским контекстом метода. В этом красота и сила замыканий Javascript — хотя методы и покинули изначальную область видимости, благодаря механизму разрешения имён, они всё ещё имеют доступ к родительской области видимости и всем переменным объявленным в ней.
Итак, главная идея заключается в том, что когда вы выносите метод из контекста, в котором он был определён, он всё равно имеет связь с родительской областью видимости. Поняв это и взяв себе на заметку, вы сможете отлично использовать этот приём (как в примере с jQuery). Это не самое глубокое объяснение замыканий, но, надеюсь, что наглядность помогла вам лучше понять этот механизм.
Ключевые слова: JavaScript, jQuery, замыкания, closures, области видимости