Открыть меню    

Шаблон модуль javascript

Зачем стоит использовать 'шаблон модуль'?

Шаблон javascript 'модуль' позволяет упорядочить большой объем javascript кода.

Структура 'шаблона модуль'?

Шаблон модуль включает в себя несколько других шаблонов javascript:

  • Объявление зависимостей
  • Пространство имен
  • Частные свойства и привилегированные свойства (методы)
  • Немедленно вызываемая функция (образует локальную область видимости)

Ниже приведена основа шаблона javascript под названием 'модуль'

javascript

var myObj = (function(){

    // определяем частную(private) переменную
    var myName = "Вася";

    // возвращается объект, содержащий общедоступные члены модуля
    return {
        getName: function(){ return myName; }
     }


}());

myObj.getName();  // Вася 

Шаблон модуль через функцию-конструктор

Шаблон модуль

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

Javascript

var myObj = (function(){

    // определяем частную(private) переменную
    var myName = "Вася";

    // конструктор
    var Constr = function(n){
        if(n === undefined)
        {
            this.myName = myName;
        }
        else
        {
            this.myName = n;
        }

    }


    // возвращается конструктор
    return Constr;


})();

var myObj_ex = new myObj();
console.log(myObj_ex.myName) // Вася

var myObjEx = new myObj("Петя");
console.log(myObjEx.myName) // Петя





Шаблон модуль, основы

Анонимные замыкания

(function () {
    // ... все переменные и функции в этом scope
    // по-прежнему сохраняют доступ ко всем глобальным
}());

Глобальный импорт

К счастью, наша анонимная функция обеспечивает простую альтернативу. Передавая глобальные как параметры анонимной функции, мы импортируем их в наш код, который становится и чище и быстрее, чем, если бы глобальные переменные были доступны из глобальной области видимости.

(function ($, YAHOO) {
    // теперь мы имеем доступ к глобальному  jQuery (как $)  YAHOO в этом коде
}(jQuery, YAHOO));

Экспорт модуля

Возвращаем значение

var MODULE = (function () {
    var my = {},
        privateVariable = 1;

    function privateMethod() {
        // ...
    }

    my.moduleProperty = 1;
    my.moduleMethod = function () {
        // ...
    };

    return my;
}());

Расширяем шаблон

Наращивание

Одно из ограничений шаблона модуль состоит в том, что весь код модуля должен быть в одном файле. Однако, кто работал над большим проектом понимает значение расщепления кода на несколько файлов. К счастью, у нас есть хорошее решение расширить модуль. Сперва мы импортируем модуль, затем добавляем свойства, затем мы экспортируем модуль. Вот пример, расширяющий наш MODULE:

var MODULE = (function (my) {
    my.anotherMethod = function () {
        // added method...
    };

    return my;
}(MODULE));

Свободное наращивание

Без предварительной инициализации модуля. Мы можем создавать гибкие из нескольких частей модули, которые можно загрузить в любом порядке со свободным наращиванием. Каждый файл доkжен иметь следующую структуру:

var MODULE = (function (my) {
    // добавляем возможности...

    return my;
}(MODULE || {}));

Сжатое/аккуратное наращивание

Свободное наращивание хорошо, но накладывает некоторые ограничения. Главное вы не можете изменить свойства модуля безопасно. Вы также не можете использовать свойства модуля из других файлов во время инициализации (но можно после выполнения инициализации). Сжатое наращивание подразумевает порядок загрузки, но позволяет переопределение. Ниже приведен пример (расширяем наш оригинальный модуль)

var MODULE = (function (my) {
    var old_moduleMethod = my.moduleMethod;

    my.moduleMethod = function () {
        // метод перезаписан, имеется доступ к старому через old_moduleMethod
    };

    return my;
}(MODULE));

Здесь мы переопределили MODULE.moduleMethod, но сохраняем ссылку на оригинальный метод, если необходимо.

Клонирование и наследование

Этот шаблон, пожалуй, наименее гибок. Он действительно дает некоторые преимущества, но происходит это за счет гибкости. Свойства, которые являются объектами или функциями не дублируются, они будут существовать как один объект с двумя ссылками. Изменив одну, поменяется другая. Это может быть исправлено для объектов при помощи рекурсии в процессе клонирования, но, возможно, не может быть исправлено для функций, кроме, возможно, с eval. Тем не менее я включил его для полноты.

var MODULE_TWO = (function (old) {
    var my = {},
        key;

    for (key in old) {
        if (old.hasOwnProperty(key)) {
            my[key] = old[key];
        }
    }

    var super_moduleMethod = old.moduleMethod;
    my.moduleMethod = function () {
        // перезаписываем клонированный метод, доступ к супер через super_moduleMethod
    };

    return my;
}(MODULE));

Подмодули

MODULE.sub = (function () {
    var my = {};
    // ...

    return my;
}());

Модули commonjs (module.exports)

Отдаем (экспортируем):

module.exports = {

}

Принимаем (импортируем):

let Model = require("./module");

Когда мы подключаем модуль, посредством require, модуль подключается всего один раз. Хоть 10 раз используйте require, модуль подключится 1 раз (код берется из КЭША).

Когда мы работаем с модулями как правило все "сбрасывается" в один файл, чтобы браузер понимал, что подключать/использовать.

//module.js
let counter = 0;
module.exports = function(){
    return ++counter;
}

//импортируем
let counter = require("module.js");
console.log(counter()); //1
console.log(counter()); //2
console.log(counter()); //3

// НО
let counter2 = require("module.js");
console.log(counter2()); //4

"Когда мы подключаем модуль посредством require, модуль подключается всего один раз." (данные берутся из КЭША) То есть мы запомнили функцию модуля с замыканием. Иначе говоря переменная counter хранится в замыкании, которая уже была заменена.

Можно воспользоваться концепцией СИНГЛТОН. Синглтон - это некий объект (сущность), которая создается всего один раз и нет возможности создать ее второй раз. Фактически наш модуль это тот же синглтон.

Какой же выход не замыкать переменные и т.д. модулю:

1. Это экспортировать функцию, которая возвращает другую функцию:

Ниже приведен шаблон модуль, который инкапсулирует данные.

//module.js
module.exports = function(){
    let counter = 0;
    return function(){
        return ++counter;
    }
}

//импортируем
let Counter = require("module.js");
let c1 = Counter();  // c1 по замыканию имеет доступ к счетчику (counter)
console.log(c1()); //1
console.log(c1()); //2
console.log(c1()); //3

let c2 = Counter();
console.log(c2()); //1
console.log(c2()); //2
console.log(c2()); //3

Модули создаются не для того, чтобы подключать их много раз. Нужно просто грамотно экспортировать из модуля что-либо. Можно также использовать значения по умолчанию:

module.exports = function(initVal){
    let counter = initVal || 0;
    return function(){
        return ++counter;
    }
}

Какой же выход не замыкать переменные и т.д. модулю:

2. (2 Способ) Это экспортировать классы:

module.exports = class {
    constructor(initVal = 0) {
        this.countre = initVal;
    }
    inc() {
        return ++this.counter;
    }
}

let Counter = require("module.js");
let c1 = new Counter();  // c1 по замыканию имеет доступ к счетчику (counter)
console.log(c1.inc()); //1
console.log(c1.inc()); //2
console.log(c1.inc()); //3

let c2 = new Counter();
console.log(c2.inc()); //1
console.log(c2.inc()); //2
console.log(c2.inc()); //3

Полезные ссылки:

источник: module pattern

сниппет: Шаблон модуль javascript, Шаблон модуль через функцию-конструктор

Модули на learn.javascript.ru

Комментарии к статье

Добавить комментарий