, это функциональное выражение. А если инструкция начинается с >function
, это объявление функции, которое требует названия, и, так как это не выражение, не может быть вызвано при помощи скобок >()
после неё. Можно представлять себе заключение в скобки как трюк, чтобы функция принудительно интерпретировалась как выражение.
Объекты в качестве интерфейсов
Представьте, что нам надо добавить ещё одну функцию в наш модуль «день недели». Мы уже не можем возвращать функцию, а должны завернуть две функции в объект.
>var weekDay = function() {
> var names = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"];
> return {
> name: function(number) { return names[number]; },
> number: function(name) { return names.indexOf(name); }
> };
>}();
>console.log(weekDay.name(weekDay.number("Воскресенье")));
>// → Воскресенье
Когда модуль большой, собирать все возвращаемые значения в объект в конце функции неудобно, потому что многие возвращаемые функции будут большими, и вам было бы удобнее их записывать где-то в другом месте, рядом со связанным с ними кодом. Удобно объявить объект (обычно называемый >exports
) и добавлять к нему свойства каждый раз, когда нам надо что-то экспортировать. В следующем примере функция модуля принимает объект интерфейса как аргумент, позволяя коду снаружи функции создать его и сохранить в переменной. Снаружи функции >this
ссылается на объект глобальной области видимости.
>(function(exports) {
> var names = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"];
> exports.name = function(number) {
> return names[number];
> };
> exports.number = function(name) {
> return names.indexOf(name);
> };
>})(this.weekDay = {});
>console.log(weekDay.name(weekDay.number("Четверг")));
>// → Четверг
Отсоединяемся от глобальной области видимости
Такой шаблон часто используется в модулях JavaScript, предназначающихся для браузера. Модуль возьмёт одну глобальную переменную и обернёт свой код в функцию, чтобы у него было своё личное пространство имён. Но с этим шаблоном бывают проблемы, когда много модулей требуют одно и то же имя, или когда вам надо загрузить две версии модуля одновременно.
Подкрутив кое-что, мы можем сделать систему, разрешающую одному модулю обращаться к интерфейсному объекту другого, без выхода в глобальную ОВ. Наша цель – функция >require
, которая, получая имя модуля, загрузит его файл (с диска или из сети, в зависимости от платформы) и вернёт соответствующее значение с интерфейсом.
Этот подход решает проблемы, упомянутые ранее, и у него есть ещё одно преимущество – зависимости вашей программы становятся явными, и поэтому сложнее случайно вызвать ненужный вам модуль без чёткого его объявления.