«Модуль» — это популярная реализация паттерна, инкапсулирующего приватную информацию, состояние и структуру, используя замыкания. Это позволяет оборачивать публичные и приватные методы и переменные в модули, и предотвращать их попадание в глобальный контекст, где они могут конфликтовать с интерфейсами других разработчиков. Паттерн «модуль» возвращает только публичную часть API, оставляя всё остальное доступным только внутри замыканий.

Это хорошее решение для того, чтобы скрыть внутреннюю логику от посторонних глаз и производить всю тяжелую работу исключительно через интерфейс, который вы определите для использования в других частях вашего приложения. Этот паттерн очень похож на немедленно-вызываемые функции (IIFE), за тем исключением, что модуль вместо функции, возвращает объект.

Важно заметить, что в JavaScript нет настоящей приватности. В отличии от некоторых традиционных языков, он не имеет модификаторов доступа. Переменные технически не могут быть объявлены как публичные или приватные, и нам приходится использовать область видимости для того, чтобы эмулировать эту концепцию. Благодаря замыканию, объявленные внутри модуля переменные и методы доступны только изнутри этого модуля. Переменные и методы, объявленные внутри объекта, возвращаемого модулем, будут доступны всем.

Ниже вы можете увидеть корзину покупок, реализованную с помощью паттерна «модуль». Получившийся компонент находится в глобальном объекте basketModule, и содержит всё, что ему необходимо. Находящийся внутри него, массив basket приватный, и другие части вашего приложения не могут напрямую взаимодействовать с ним. Массив basket существует внутри замыкания, созданного модулем, и взаимодействовать с ним могут только методы, находящиеся в том же контексте (например, addItem(), getItem()).

var basketModule = (function() {
  var basket = []; // приватная переменная
    return { // методы доступные извне
        addItem: function(values) {
            basket.push(values);
        },
        getItemCount: function() {
            return basket.length;
        },
        getTotal: function() {
           var q = this.getItemCount(),p=0;
            while(q--){
                p+= basket[q].price; 
            }
            return p;
        }
    }
}());

Внутри модуля, как вы заметили, мы возвращаем объект. Этот объект автоматически присваивается переменной basketModule, так что с ним можно взаимодействовать следующим образом:

// basketModule - это объект со свойствами, которые могут также быть и методами:
basketModule.addItem({item:'bread', price:0.5});
basketModule.addItem({item:'butter', price:0.3});

console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());

// А следующий ниже код работать не будет:
console.log(basketModule.basket); // undefined потому что не входит в возвращаемый объект
console.log(basket); // массив доступен только из замыкания

Методы выше фактически помещены в неймспейс basketModule.

Исторически, паттерн «модуль» был разработан в 2003 году группой людей, в число которых входил Ричард Корнфорд. Позднее этот паттерн был популяризован Дугласом Крокфордом в его лекциях, и открыт заново в блоге YUI благодаря Эрику Мирагилиа.

Давайте посмотрим на реализацию «модуля» в различных библиотеках и фреймворках.

Dojo

Dojo старается обеспечивать поведение похожее на классы с помощью dojo.declare, который, кроме создания «модулей», также используется и для других вещей. Давайте попробуем, для примера, определить basket как модуль внутри неймспейса store:

// традиционный способ
var store = window.store || {};
store.basket = store.basket || {};

// с помощью dojo.setObject
dojo.setObject("store.basket.object", (function() {
    var basket = [];
    function privateMethod() {
        console.log(basket);
    }
    return {
        publicMethod: function() {
            privateMethod();
        }
    };
}()));

Лучшего результата можно добиться, используя dojo.provide и миксины.

YUI

Следующий код, по большей части, основан на примере реализации паттерна «модуль» в фреймворке YUI, разработанным Эриком Миргалиа, но более самодокументирован.

YAHOO.store.basket = function () {

    // приватная переменная:
    var myPrivateVar = "Ко мне можно получить доступ только из YAHOO.store.basket.";

    // приватный метод:
    var myPrivateMethod = function() {
        YAHOO.log("Я доступен только при вызове из YAHOO.store.basket");
    }

    return {
        myPublicProperty: "Я - публичное свойство",
        myPublicMethod: function() {
            YAHOO.log("Я - публичный метод");

            // Будучи внутри корзины я могу получить доступ к приватным переменный и методам:
            YAHOO.log(myPrivateVar);
            YAHOO.log(myPrivateMethod());

            // Родной контекст метода myPublicMethod сохранён
            // поэтому мы имеет доступ к this
            YAHOO.log(this.myPublicProperty);
        }
    };

}();

jQuery

Существует множество способов, чтобы представить jQuery-код в виде паттерна «модуль», даже если этот код не напоминает привычные jQuery-плагины. Бен Черри ранее предлагал способ, при котором, если у модулей есть общие черты, то они объявляются через функцию-обертку.

В следующем примере функция library используется для объявления новой библиотеки и автоматически при создании библиотеки (т.е. модуля), связывает вызов метода init с document.ready.

function library(module) {
  $(function() {
    if (module.init) {
      module.init();
    }
  });
  return module;
}

var myLibrary = library(function() {
   return {
     init: function() {
       /* код модуля */
     }
   };
}());

Ссылки по теме:
Бен Черри — Погружение в паттерн «Модуль»
Джон Ханн — Будущее — это модули, а не фреймворки
Натан Смит — Ссылки на window и document в модулях (gist)

Рекомендуем почитать:
Книги по JavaScript на ozon.ru
Книги по JavaScript на books.ru
Книги по JavaScript на my-shop.ru