В разделе 8.8 говорилось, что замыкание – это функция вместе с областью види_ мости, которая действовала на момент определения функции.1 Определяя функ_
1 Замыкания – это тема повышенной сложности. Если вы пропустили обсуждение замыканий в главе 8, вам необходимо сначала прочитать о замыканиях, а затем вернуться к этому разделу.
10.2. Импорт символов из пространств имен
цию таким способом, появляется возможность использовать локальную область видимости как пространство имен. Вложенные функции, объявляемые внутри объемлющих функций, имеют возможность доступа к таким частным простран_ ствам имен. Подобный подход имеет два преимущества. Первое основано на том, что поскольку частное пространство имен является первым объектом в цепочке областей видимости, функции в частном пространстве имен могут ссылаться на другие функции и свойства в этом же пространстве имен без необходимости ука_ зывать полные имена.
Второе преимущество заключается в том, что эти пространства имен действи_ тельно являются частными. Нет никакой возможности обратиться к символам, объявленным внутри функции, за ее пределами. Эти символы будут доступны во внешнем, общедоступном пространстве имен, только если функция экспортиру_ ет их. Это означает, что модуль может экспортировать только общедоступные функции и скрыть подробности реализации, такие как служебные методы и пе_ ременные внутри замыканий.
Эту возможность иллюстрирует пример 10.4. Здесь с помощью замыкания соз_ дается частное пространство имен, после чего общедоступные методы экспорти_ руются в общедоступное пространство имен.
Пример 10.4. Определение частного пространства имен с помощью замыкания
// Создать объект пространства имен.
// Для краткости проверка ошибок отсутствует. var com;
if (!com) com = {};
if (!com.davidflanagan) com.davidflanagan = {}; com.davidflanagan.Class = {};
// Здесь ничего не создается непосредственно в пространстве имен.
// Вместо этого объявляется и вызывается анонимная функция, которая
// создает замыкание, используемое как частное пространство имен.
// Данная функция экспортирует общедоступные символы из замыкания
// в объект com.davidflanagan.Class
// Обратите внимание: функция не имеет имени, поэтому не создается
// никаких глобальных символов.
(function( ) { // Начало определения анонимной функции
// Вложенные функции создают символы внутри замыкания function define(data) { counter++; /* тело функции */ } function provides(o, c) { /* тело функции */ }
// Локальные переменные – это символы, расположенные внутри замыкания.
// Этот символ останется частным и будет доступен только внутри замыкания var counter = 0;
// Эта функция может обращаться к переменной с помощью простого имени
// и не пользоваться полным именем, определяющим пространство имен function getCounter( ) { return counter; }
// Теперь, когда внутри замыкания были определены свойства,
// которые должны оставаться частными, можно экспортировать символы,
// доступные во внешнем пространстве имен
var ns = com.davidflanagan.Class; ns.define = define;
ns.provides = provides;
208 Глава 10. Модули и пространства имен
ns.getCounter = getCounter;
})( ); // Конец определения анонимной функции и ее вызов