Як використовувати шаблон розкриття модуля в JavaScript


78

Я натрапив на цю публікацію: шаблон модуля виявлення JavaScript . Я хотів би використовувати це у своєму проекті.

Давайте уявимо, що у мене є функція, abcі я викликаю цю функцію у своєму головному файлі JavaScript.

Чи цей шаблон робить речі різними? Хто-небудь може показати мені основний приклад цієї моделі?


3
Для мене ця стаття - найкраще пояснення, яке я бачив на сьогодні.
Мохаммад Сепахванд

2
Навіщо використовувати шаблон виявлення модуля, коли ви можете використовувати остаточний шаблон модуля? github.com/tfmontague/definitive-module-pattern
tfmontague

Відповіді:


98

Невеликий приклад:

var revealed = function(){
   var a = [1,2,3];
   function abc(){
     return (a[0]*a[1])+a[2];
   }

   return {
      name: 'revealed',
      abcfn: abc
   }
}();

в анонімній функції, яка ініціюється для надання revealedзначення, aі abcє приватною для цієї функції. Функція повертає об’єктний літерал із nameвластивістю та abcfnвластивістю, який є посиланням на abc function. abc functionВикористовує приватну змінну a. Це все можна зробити завдяки використанню замикань (на все, що знаходиться в межах функції, може посилатися все інше в цій самій функції).

Виявлене використання:

alert(revealed.name);    //=> 'revealed'
alert(revealed.abcfn()); //=> 5 (1*2+3)

8
ця закономірність змінила моє життя!
klewis

6
Я знаю, що це старе, але у поверненому значенні abc () відсутня дужка =]
Філіп Пейтон

Навіщо використовувати шаблон виявлення модуля, коли ви можете використовувати остаточний шаблон модуля? github.com/tfmontague/definitive-module-pattern
tfmontague

Як створити новий екземпляр виявленого?
Neon Warge

@NeonWarge: ти ні. Функція не є конструктором. Він повертає об’єктний літерал, в якому aі abcзакриті.
KooiInc

23

DC = Дуглас Крокфорд
RMP = Шаблон модуля розкриття

Різниця між DC та RMP в основному є організаційною / зрозумілою

Приклад представлений у самій статті? І що саме ви запитуєте, оскільки ці речі не мають нічого спільного з файлами, а скоріше із закриттям.

Ви поміщаєте все в закриття (функцію) і виставляєте лише ту частину, до якої хочете отримати доступ. Різниця між стилем постійного струму та RMP полягає в тому, що в першій функції функції визначаються в різних місцях, тоді як у RMP вони завжди визначаються в одному і тому ж місці, а потім виявляються в літералі загальнодоступного об'єкта.

Отже, в DC та RMP у вас є:

  • закриття, що дозволяє визначити приватні частини (змінні та функції)
  • приватна частина
  • публічний результат, який визначає загальнодоступні функціональні можливості та змінні (стан)

Ці дві закономірності відрізняються лише читабельністю. У випадку постійного струму ви не завжди можете знати, де буде визначена певна функціональність, але в RMP ви завжди знаєте, що все є в приватній частині.


1
Це неправда, що DC і RMP однакові - ці два дуже різні, коли справа стосується спадкування. Наприклад, див. Stackoverflow.com/questions/21925720/…
I-Lin Kuo


6

Метод, названий автором "шаблон Дугласа Крокфорда для створення об'єктів", насправді є модульним шаблоном, який був розроблений переважно Річардом Корнфордом та ін . Див. Http://groups.google.com/group/comp.lang.javascript/msg/9f58bd11bd67d937

Що стосується прикладів, то їх багато. Прочитайте наступну статтю та перейдіть за деякими посиланнями: http://peter.michaux.ca/articles/module-pattern-provides-no-privacy-at-least-not-in-javascript-tm


Я переробив свій пост, будь ласка, дайте мені знати, якщо ще є якісь проблеми :)
Алекс

Цікаво, як ці речі змінюються з часом. Дефіцитну версію використовував Девід Марк ( відомий MyLibrary ) деякий час, я не маю жодних проблем з версією, що не показує, тому я її використовую. :-)
RobG

1

Мені подобається використовувати суміш розкриваючого шаблону модуля з одиночним шаблоном, щоб я міг зберігати структурований код з перевагами шаблону модуля:

var MyFunction = function(){

    var _ = {
       Init: function(){
          _.Config.foo = "hello world";
       },
       Config:{
          foo:null
       },
       ShowAlert:function(){
          alert(_.Config.foo);
       }
    }

    return {
        Init: _.Init,
        ShowAlert: _.ShowAlert
    };
}();

MyFunction.Init();
MyFunction.ShowAlert();

Я написав більше інформації про це у своєму блозі:

http://curtistimson.co.uk/js/mixing-revealing-module-and-singleton-javascript-patterns/


1

Просто хочу додати: за цим шаблоном добре передавати глобальні залежності як аргументи / параметри, щоб вони були явними. Вам не потрібно це робити, але це з першого погляду дає зрозуміти, що потрібно вашому модулю. Наприклад:

var myModule = (function ($, loadModule) {
  "use strict";
})(jQuery, load);

У цьому прикладі ви можете побачити відразу в 1-му рядку, що ваш модуль використовує jQuery та деякі інші модулі, відповідальні за завантаження функціональних можливостей.


0

Для коду поза модулем це не має великої різниці. У всіх 3 випадках у цій статті методи називаються однаково. Але структура самого модуля внутрішньо відрізняється.

Структура модуля Крокфорда та те, що вони називають "показовою схемою модуля", є структурно майже однаковою. Єдина відмінність полягає в тому, що вони спочатку призначають метод локальному змінному, щоб бути більш читабельним. Але насправді в цьому немає нічого особливого, і у вас є кілька прикладів тут, у вашому посиланні.


Об'єкт, повернутий за допомогою розкриваючого шаблону модуля, не поводиться як шаблон модуля Дугласа Крокфорда щодо перевизначення (див. Попередження Адді Османі за адресою addyosmani.com/resources/essentialjsdesignpatterns/book/… ).
I-Lin Kuo

0

Основна концепція модуля виявлення полягає в тому, що у вас є файл, Objectякий інкапсулює його дані та поведінку:

var Module = (function(){
    var privateStuff = {};
    var publicStuff = {};

    return publicStuff;
})();

Однак є кілька найкращих практик, які слід використовувати, використовуючи цей шаблон. Ось модуль (" Modulus") з деякими властивостями для демонстрації, який використовує деякі з цих практик:

function AbstractSomeClass(id) {
    this.id = id;
    return this;
}

var Modulus = (new (function SomeClass() {
    var thus = this;

    function NameClass(name){
        this.value = thus.name || name;
    }

    AbstractSomeClass.call(this, 998);

    this.name = 'Touring';
    this.name = ( new NameClass('Hofstadter') ).value;

    return {
        id: this.id,
        name: this.name
    };
})());

Зверніть увагу на (new (function SomeClass(){ ... })());синтаксис. Використання newподібного дозволяє вам використовувати thisключове слово всередині закриття. Це зручно, якщо вам потрібно успадкувати властивості з іншого класу ( AbstractSomeClass.call(this, 998);) - Однак вам все одно доведеться розкрити властивості, які ви хотіли б мати загальнодоступними, наприклад:

return {
    id: this.id,
    name: this.name
};

Також зверніть увагу , що ми відносимо thisдо thus- що дозволяє використовувати батьківський , thisвсередині підкласу , який має свою власну thisсферу ( this.value = thus.name || name;)

Ще раз, це лише декілька запропонованих конвенцій та найкращих практик.


0

Ось невеликий приклад виявлення шаблону модуля.

Він надає можливість оголосити приватні та публічні функції так само, як клас. Це є основними перевагами цих шаблонів. Якщо ми не хочемо виставляти деякі функціональні можливості, доступні у всьому світі, то робить їх приватними, а решту зробити загальнодоступними. Нижче це приклад створення приватних та публічних функцій. І ще одна річ - це самостійно виконуваний блок коду.

  var Calculator = (function () {

        var num1 = 10;
        var num2=5
        var _abc = function () {
            return num1 - num2;
        };

        var _mulFunc = function () {
            return num1 * num2;
        };

        var _divFunc = function () {
            return num1/num2;
        };

        return {
           //public scope
            abc: _abc,
            mulFunc:_mulFunc
         };

    })();

попередження (Calculator.abc ()); він повертає 5

попередження (Calculator.mulFunc ()); він повертає 50

А __divFunc () не буде доступним, оскільки він знаходиться в приватній області. Ми можемо отримати доступ лише до тих функцій, які оголошені всередині об'єкта return, оскільки це представлення загальнодоступної функції


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.