Шрифт:
Этого можно добиться, определив модуль (в данном случае класс
Set
) внутри функции. Как описывалось в разделе 8.5, переменные и функции, объявленные внутри другой функции, являются локальными по отношению к этой функции и недоступны извне. Таким образом, область видимости функции (называемой иногда «функцией модуля») можно использовать как частное пространство имен модуля. Пример 9.24 демонстрирует, как это может выглядеть применительно к нашему классу Set
. Пример 9.24. Класс Set внутри функции модуля
// Объявляет глобальную переменную Set и присваивает ей значение, возвращаемое
// функцией. Круглые скобки, окружающие объявление функции, свидетельствуют о том,
// что функция будет вызвана сразу после ее объявления и что присваивается значение,
// возвращаемое функцией, а не сама функция. Обратите внимание, что это выражение
// определения функции, а не инструкция, поэтому наличие имени "invocation"
// не вызывает создание глобальной переменной,
var Set = (function invocation {
function Set { // Эта функция-конструктор - локальная переменная,
this.values = {}; // Свойство для хранения множества
this.n = 0; // Количество значений в множестве
this.add.apply(this, arguments); // Все аргументы являются значениями,
} // добавляемыми в множество
// Далее следуют определения методов в Set.prototype.
// Для экономии места программный код опущен
Set.prototype.contains = function(value) {
// Обратите внимание, что v2s вызывается без префикса Set._v2s
return this.values.hasOwnProperty(v2s(value));
};
Set.prototype.size = function { return this.n; };
Set.prototype.add = function { /* ... */ };
Set.prototype.remove = function { /* ... */ };
Set.prototype.foreach = function(f, context) {/*...*/>;
// Далее следуют вспомогательные функции и переменные, используемые
// методами выше. Они не являются частью общедоступного API модуля и скрыты
// в области видимости функции, благодаря чему не требуется объявлять их как
// свойства класса Set или использовать символ подчеркивания в качестве префикса.
function v2s(val) { /* ... */ }
function objectld(o) { /* ... */ }
var nextId = 1;
// Общедоступным API этого модуля является функция-конструктор Set.
// Нам необходимо экспортировать эту функцию за пределы частного
// пространства имен, чтобы ее можно было использовать за ее пределами.
// В данном случае конструктор экспортируется за счет передачи его
// в виде возвращаемого значения. Он становится присваиваемым значением
// в выражении в первой строке выше, return Set;
}); // Вызвать функцию сразу после ее объявления.
Обратите внимание, что такой прием вызова функции сразу после ее определения является характерным для языка JavaScript. Программный код, выполняемый в частном пространстве имен, предваряется текстом
«(function {
» и завершается «});
». Открывающая круглая скобка в начале сообщает интерпретатору, что это выражение определения функции, а не инструкция, поэтому в префикс можно добавить любое имя функции, поясняющее ее назначение. В примере 9.24 было использовано имя «invocation
», чтобы подчеркнуть, что функция вызывается сразу же после ее объявления. Точно так же можно было бы использовать имя «namespace
», чтобы подчеркнуть, что функция играет роль пространства имен.