Javascript. Шаблоны проектирования. Шаблон «модуль».
Шаблон «модуль» получил широкое распространение благодаря предоставляемой им возможности структурировать и организовать программный код по мере увеличения его объема.
В отличие от других языков, в JavaScript отсутствует специальная синтаксическая конструкция для создания пакетов, но шаблон «модуль» обеспечивает все необходимое для создания независимых фрагментов программного кода, которые можно рассматривать как «черные ящики» и добавлять, заменять или удалять их из своей программы в соответствии с потребностями (возможно, изменяющимися с течением времени) вашей программы.
Шаблон «модуль», удобно использовать совместно с описанной ранее конструкцией создания пространства имен.
MYAPP.namespace("MYAPP.modules.array"); MYAPP.modules.array = (function () { return { // будет реализовано позже } }());
Затем можно добавить общедоступные методы:
MYAPP.modules.array = (function () { return { inArray: function (needle, hayStack) { // ... }, isArray: function (a) { // … } } }());
В частной области видимости, образуемой немедленно вызываемой функцией, можно объявить частные свойства и методы, если это необходимо.
Окончательный результат - объект, возвращаемый немедленно вызываемой функцией, содержащий общедоступные члены модуля:
MYAPP.namespace("MYAPP.utilities.array"); MYAPP.utilities.array = (function () { // зависимости var uobj = MYAPP.utilities.object, ulang = MYAPP.utilities.lang, // частные свойства array_string = "[object Array]", ops = Object.prototype.toString; // частные методы // ... // конец инструкции var // реализация необязательной процедуры инициализации // ... // общедоступные члены return { inArray: function (needle, haystack) { for (var i = 0, max = haystack.length; i < max; i += 1) { if (haystack[i] === needle) { return true; } } } , isArray: function (а) { return ops.call(a) === array_string; } // … другие методы и свойства }; }());
Шаблон «модуль» широко используется на практике и является рекомендуемым способом организации программного кода, особенно по мере увеличения его объема.
Модули, создающие конструкторы
В предыдущем примере создается объект MYAPP.utilities.array, но иногда гораздо удобнее создавать объекты с помощью конструкторов. Для этой цели также можно использовать шаблон «модуль». Единственное отличие состоит в том, что немедленно вызываемая функция, обертывающая модуль, возвращает функцию, а не объект.
Взгляните на следующий пример использования шаблона «модуль», который создает функцию-конструктор MYAPP.utilities. Array:
MYAPP.namespace("MYAPP.modules.Array"); MYAPP.modules.Array = (function () { // зависимости var uobj = MYAPP.modules.object, ulang = MYAPP.modules.lang, // частные свойства и методы... Constr; // конец инструкции var // реализация необязательной процедуры инициализации // ... // общедоступные методы -- конструктор Constr = function (о) { this.elements = this.toArray(o); }; // общедоступные методы -- прототип Constr.prototype = { constructor: MYAPP.utilities.Array, version: "2.0", toArray: function (obj) { for (var i = 0, a = [], len = obj.length; i < len; i += 1) { a[i] = obj[i]; } return a; } }; // вернуть конструктор, // создающий новое пространство имен return Constr; }());
Импортирование глобальных переменных в модули
В одной из распространенных разновидностей шаблона предусматривается возможность передачи аргументов в немедленно вызываемую функцию, обертывающую модуль.
Функции можно передавать любые значения, но на практике ей обычно передаются ссылки на глобальные переменные и иногда даже сам глобальный объект.
Импортирование глобальных переменных позволяет увеличить скорость разрешения глобальных имен внутри немедленно вызываемой функции благодаря тому, что импортируемые переменные становятся локальными для этой функции:
MYAPP.modules.module = (function (арр, global) { // ссылки на объект global // и на глобальное пространство имен арр // теперь будут локальными переменными }(MYAPP, this));