Механизм, который позволяет скрывать переменные и методы реализуется благодаря замыканиям (сlosures). Внутренняя функция всегда имеет доступ к переменным и параметрам своей внешней функции, даже после того как внешняя функция закончила выполняться. Это чрезвычайно мощное свойство языка.
var Module = function () {
var private = 100;
this.getPrivate = function () {
return private;
};
};
Единственным способом получить доступ к переменной private — это вызвать привилегированный метод getPrivate . В этом примере замыканием служит первая функция, которая ограничивает область видимости.
Это один из шаблонов, который можно использовать для написания модулей. Когда создается новый экземпляр Module , то все содержимое конструктора вместе с локальными и привилегированными полями копируется благодаря замыканию. Этот шаблон не эффективен по расходу памяти, зато достаточно просто и надежен.
Другое применение замыкание находит в обработчиках событий.
Допустим, мы хотим отобразить список из названий предметов, а по клику на названии получить детальную информацию о предмете.
function drawList(items) {
var i, li;
for (i = 0; i < items.length; i++) {
li = $('<li class="item">' + items[i].name + '</li>').appendTo(root);
li.click(function () {
alert(items[i].data);
});
}
}
Этот пример не будет работать, как мы ожидаем потому, что переменная i внутри обработчика события click не соответствует порядковому номеру элемента в списке. Значение этой переменной всегда будет равно items.length.
Чтобы пример заработал, обернем обработчик в замыкание.
(function (i) {
li.click(function () {
alert(items[i].data);
});
})(i);
Или можно сразу получить требуемый элемент.
(function (item) {
li.click(function () {
alert(item.data);
});
})(items[i]);
Можно заметить, что замыкания — это просто анонимные функции. Нам нет нужды выносить эти вспомогательные функции на основной уровень и тем более давать им имена.