JavaScript. Подробное руководство, 6-е издание, стр. 138

<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 отсутствуют инструменты управления модулями, вам придется использовать средства создания и экспортирования модулей, которые лучше подходят для используемой вами библиотеки инструментов.