Подтвердить что ты не робот

Дизайн шаблона JavaScript: разница между шаблоном модуля и раскрытием шаблона модуля?

В последнее время я читаю книгу "Изучение шаблонов JavaScript". То, что я не получаю, - это различие между шаблоном модуля и раскрытием шаблона модуля. Я чувствую, что они одно и то же. Любой может привести пример?

4b9b3361

Ответ 1

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

Шаблон базового модуля

Шаблон модуля должен удовлетворять следующему:

  • Частные члены живут в закрытии.
  • Открытые элементы отображаются в возвращаемом объекте.

Но в этом определении много неопределенности. Устраняя двусмысленность по-разному, вы получаете варианты шаблона модуля.

Шаблон раскрывающего модуля

Шаблон раскрывающегося модуля - самый известный и самый популярный из вариантов модуля. Он имеет ряд преимуществ по сравнению с другими альтернативами, такими как

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

RMP удовлетворяет трем дополнительным условиям в дополнение к оригиналу:

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

В следующем примере показано, как он используется

var welcomeModule = (function(){
  var name = "John";
  var hello = function(){ console.log("Hello, " + name + "!");}
  var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return {
    name: name,
    sayHello: hello,
    sayWelcome: welcome
  }
})();

Если вы хотите сделать private name и sayHello частным, вам просто нужно прокомментировать соответствующие строки в возвращаемом объекте.

var welcomeModule = (function(){
  var name = "John";
  var hello = function(){ console.log("Hello, " + name + "!");}
  var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return {
    //name: name,
    //sayHello: hello,
    sayWelcome: welcome
  }
})();

Шаблон модуля с условным литералом

Это, вероятно, самый старый вариант шаблона модуля. В отличие от RMP, нет никакого официального официального названия для этого варианта.

В дополнение к оригиналу оно удовлетворяет следующим условиям:

  • Частные члены определены в закрытии.
  • Открытые элементы определяются в литерале возвращаемого объекта.
  • Ссылки на публичных пользователей доступны по this, когда это возможно.

В следующем примере вы можете увидеть, как, в отличие от RMP, определения функций фактически находятся в литеральном объекте return, а ссылки на члены - this.

var welcomeModule = (function(){
  return {
    name: "John",
    sayHello: function(){ console.log("Hello, " + this.name + "!");}
    sayWelcome: function() { console.log( this.hello() + " Welcome to StackOverflow!");}
  }
})();

Обратите внимание, что разблокировать RMP, чтобы сделать name и sayHello private, ссылки, указывающие на name и sayHello в различных определениях тела функции, также должны быть изменены.

var welcomeModule = (function(){
  var name: "John";
  var sayHello = function(){ console.log("Hello, " + name + "!");};
  return {
    //name: "John",
    //sayHello: function(){ console.log("Hello, " + this.name + "!");}
    sayWelcome: function() { console.log( hello() + " Welcome to StackOverflow!");}
  }
})();

Шаблон модуля с заглушкой объекта возврата

Этот вариант также не имеет официального имени.

В дополнение к оригиналу оно удовлетворяет следующим условиям:

  • Пустой пустой объект возвращается в начале.
  • Частные члены определены в закрытии.
  • Публичные члены определяются как члены заглушки
  • Ссылки на публичные элементы через объект-заглушку

Используя наш старый пример, вы можете увидеть, что публичные элементы напрямую добавляются в объект-заглушку.

var welcomeModule = (function(){
  var stub = {};
  stub.name = "John";
  stub.sayHello = function(){ console.log("Hello, " + stub.name + "!");}
  stub.sayWelcome = function() { console.log( stub.hello() + " Welcome to StackOverflow!");}
  return stub;
})();

Если вы хотите сделать private name и sayHello приватным, как и раньше, ссылки на члены теперь-private должны быть изменены.

var welcomeModule = (function(){
  var stub = {};
  var name = "John";
  var sayHello = function(){ console.log("Hello, " + name + "!");}

  stub.sayWelcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return stub;
})();

Резюме

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

Недостатком этого шаблона является то, что если частная функция относится к публичной функции, эта публичная функция не может быть переопределена, если требуется патч. Это связано с тем, что частная функция будет продолжать ссылаться на частную реализацию, и шаблон не применяется к публичным членам, а только к функциям.

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

В результате этого модули, созданные с помощью шаблона Revealing Module, могут быть более хрупкими, чем те, которые были созданы с использованием исходного шаблона модуля, поэтому следует соблюдать осторожность во время использования.

и о котором я говорил в некоторых других сообщениях.

Ответ 2

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

Я создал раскрывающий модуль с последующим кодом.

var HTMLChanger = (function () {
    var privateFunc = function () {
        this.sayHello();
    }

    var hello = function () {
        console.log('say Hello');
    }
    var callPrivate = function () {
        privateFunc.call(this);
    }


    return {
        sayHello: hello,
        callPrivate: callPrivate
    };
})();

HTMLChanger.callPrivate();
//say Hello

HTMLChanger.sayHello = function() { console.log('say Hi!') };

HTMLChanger.callPrivate();
//say Hi!

Как вы можете видеть, мы можем переопределить открытый элемент.

Ответ 3

Краткий ответ. В модуле модуля мы определяем функции в возвращаемом объекте.

В шаблоне Revealing Module мы определяем функции в области закрытия и используем только имена переменных в возвращаемом объекте.

Это упрощает код и имеет множество других преимуществ