<b> // свойства класса Set или использовать символ подчеркивания в качестве префикса.</b>
<b> function v2s(val) { /* ... */ }</b>
<b> function objectld(o) { /* ... */ }</b>
<b> var nextId = 1;</b>
<b> // Общедоступным API этого модуля является функция-конструктор Set().</b>
<b> // Нам необходимо экспортировать эту функцию за пределы частного</b>
<b> // пространства имен, чтобы ее можно было использовать за ее пределами.</b>
<b> // В данном случае конструктор экспортируется за счет передачи его</b>
<b> // в виде возвращаемого значения. Он становится присваиваемым значением</b>
<b> // в выражении в первой строке выше, return Set;</b>
<b>}()); // Вызвать функцию сразу после ее объявления.</b>
Обратите внимание, что такой прием вызова функции сразу после ее определения является характерным для языка JavaScript. Программный код, выполняемый в частном пространстве имен, предваряется текстом
<b>«(function() {</b>
» и завершается «
<b>}());</b>
». Открывающая круглая скобка в начале сообщает интерпретатору, что это выражение определения функции, а не инструкция, поэтому в префикс можно добавить любое имя функции, поясняющее ее назначение. В примере 9.24 было использовано имя «
<b>invocation</b>
», чтобы подчеркнуть, что функция вызывается сразу же после ее объявления. Точно так же можно было бы использовать имя «
<b>namespace</b>
», чтобы подчеркнуть, что функция играет роль пространства имен.
После того как модуль окажется заперт внутри функции, ему необходим некоторый способ экспортировать общедоступный API для использования за пределами функции модуля. В примере 9.24 функция модуля возвращает конструктор, который тут же присваивается глобальной переменной. Сам факт возврата значения из функции ясно говорит о том, что оно экспортируется за пределы области видимости функции. Модули, определяющие более одного элемента API, могут возвращать объект пространства имен. Для нашего модуля с классами множеств можно было бы написать такой программный код:
<b>// Создает единственную глобальную переменную, хранящую все модули,</b>
<b>// имеющие отношение к коллекциям</b>
<b>var collections;</b>
<b>if (!collections) collections = {};</b>
<b>// Теперь определить модуль sets</b>
<b>collections.sets = (function namespace() {</b>
<b> // Здесь находятся определения различных классов множеств,</b>
<b> // использующих локальные переменные и функции </b>
<b> // ... Большая часть программного кода опущена...</b>
<b> // Экспортировать API в виде возвращаемого объекта пространства имен </b>
<b> return {</b>
<b> // Экспортируемое имя свойства : имя локальной переменной </b>
<b> AbstractSet: AbstractSet,</b>
<b> NotSet: NotSet,</b>
<b> AbstractEnumerableSet: AbstractEnumerableSet,</b>
<b> SingletonSet: SingletonSet,</b>
<b> AbstractWritableSet: AbstractWritableSet,</b>
<b> ArraySet: ArraySet</b>
<b> };</b>
<b>}());</b>
Можно предложить похожий прием, определив функцию модуля как конструктор, который будет вызываться с ключевым словом
<b>new</b>
и экспортировать значения за счет их присваивания:
<b>var collections;</b>
<b>if (!collections) collections = {};</b>
<b>collections.sets = (new function namespace() {</b>
<b> // ... Большая часть программного кода опущена ...</b>
<b> // Экспортировать API в объекте this</b>
<b> this.AbstractSet = AbstractSet;</b>
<b> this.NotSet = NotSet; // И так далее...</b>
<b> // Обратите внимание на отсутствие возвращаемого значения.</b>
<b>}());</b>
Если объект глобального пространства имен уже определен, функция модуля может просто присваивать значения свойствам этого объекта и вообще ничего не возвращать:
<b>var collections;</b>
<b>if (!collections) collections = {};</b>
<b>collections.sets = {};</b>
<b>(function namespace() {</b>
<b> // ... Большая часть программного кода опущена ...</b>
<b> // Экспортировать общедоступный API в объект пространства имен, созданный выше</b>
<b> collections.sets.AbstractSet = AbstractSet;</b>
<b> collections.sets.NotSet = NotSet; // И так далее...</b>
<b> // Инструкция return не требуется, потому что экспортирование выполняется выше.</b>
<b>}());</b>
Фреймворки, реализующие инструменты загрузки модулей, могут предусматривать собственные методы экспортирования API модулей. Внутри модуля может определяться функция
<b>provides(),</b>
которая выполняет регистрацию его API, или объект
<b>exports</b>
, в котором модуль должен сохранять свой API. Пока в языке JavaScript отсутствуют инструменты управления модулями, вам придется использовать средства создания и экспортирования модулей, которые лучше подходят для используемой вами библиотеки инструментов.