Шаблоны проектирования JavaScript: модуль

Опубликованные в JavaScript модули — наиболее часто используемые шаблоны, которые применяются для обеспечения независимости отдельных фрагментов кода от других компонентов. Это создает слабую связанность, необходимую для поддержки хорошо структурированного кода.

Если вы знакомы с объектно-ориентированными языками, вы знаете, что модули — это «классы» JavaScript. Одним из многих преимуществ классов является инкапсуляция — предотвращение доступа других классов к  состоянию и поведению. Шаблон модуля допускает публичный и частный (плюс малоизвестные защищенный и привилегированный) уровни доступа.

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

(function() {

    // declare private variables and/or functions

    return {
        // declare public variables and/or functions
    }

})();

Здесь мы создаем частные переменные и/или функции перед возвратом объекта, который нам нужен. Код за пределами закрытой скобки не сможет получить доступ к этим переменным, поскольку он не находится в той же области. Возьмем, к примеру, более конкретную реализацию:

var HTMLChanger = (function() {
    var contents = 'contents'

    var changeHTML = function() {
    var element = document.getElementById('attribute-to-change');
    element.innerHTML = contents;
    }

    return {
    callChangeHTML: function() {
        changeHTML();
        console.log(contents);
    }
    };

})();

HTMLChanger.callChangeHTML();       // Outputs: 'contents'
console.log(HTMLChanger.contents);  // undefined

Обратите внимание, что callChangeHTML привязывается к возвращаемому объекту, и на него можно ссылаться в пространстве имен HTMLChanger. Однако за пределами модуля на данный контент ссылаться нельзя.

Выявляющий модульный шаблон

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

var Exposer = (function() {
    var privateVariable = 10;

    var privateMethod = function() {
    console.log('Inside a private method!');
    privateVariable++;
    }

    var methodToExpose = function() {
    console.log('This is a method I want to expose!');
    }

    var otherMethodIWantToExpose = function() {
    privateMethod();
    }

    return {
        first: methodToExpose,
        second: otherMethodIWantToExpose
    };
})();

Exposer.first();        // Output: This is a method I want to expose!
Exposer.second();       // Output: Inside a private method!
Exposer.methodToExpose; // undefined

Он выглядит намного чище, однако у него есть очевидный недостаток — невозможность ссылаться на частные методы, что может создать проблемы во время тестирования. Кроме того, вы не можете переопределить публичное поведение.

Читайте также: Шаблоны проектирования JavaScript: наблюдатель

Tags:

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