В чем разница между этими двумя шаблонами JavaScript

#javascript #design-patterns

#javascript #шаблоны проектирования

Вопрос:

Я пытаюсь лучше организовать свой JavaScript. Моя цель — иметь модульную архитектуру, которую я могу разбить на отдельные файлы (sitename.js , sitename.utils.js и т.д.).

Я хотел бы знать, каковы преимущества и недостатки этих двух шаблонов и какой из них больше подходит для разбиения на модули, которые находятся в отдельных файлах.

ШАБЛОН # 1 (шаблон модуля)

 var MODULE = (function () {

    //private methods

    return {
        common: {
            init: function() {
                console.log("common.init");
            }
        },
        users: {
            init: function () {
                console.log("users.init");
            },
            show: function () {
                 console.log("users.show");
            }
        }
    }
})();
  

ШАБЛОН # 2 (одноэлементный)

 var MODULE = {
  common: {
    init: function() {
        console.log("common.init");
    }
  },

  users: {
    init: function() {
      console.log("users.init");
    },

    show: function() {
      console.log("users.show");
    }
  }
};
  

Комментарии:

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

Ответ №1:

Лично я рекомендую расширение # 1 следующим образом:

 var Module = (function(Module) {
  // A comment
  Module.variable1 = 3;

  /**
   * init()
   */
  Module.init = function() {
    console.log("init");
  };

  // ...

  return Module;
})(Module || {});
  

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

Например, модуль if.Пользователи должны были перейти в свой собственный файл:

 var Module = Module || {};
Module.Users = (function(Users) {
  /**
   * init()
   */
  Users.init = function() {
    console.log("Module.Users.init");
  };

  // ...

  return Users;
})(Module.Users || {});
  

Теперь «module.js » и «module.users.js » это могут быть отдельные файлы, и они будут работать независимо от порядка их загрузки. Также обратите внимание на локальную область действия имени модуля — это очень удобно, если имя вашего модуля длинное, потому что вы можете взять «MyApp.Users.EditScreen» и ссылаться на него с помощью переменной типа «ES» в рамках определения вашего модуля.

Комментарии:

1. Новый шаблон также позволяет дополнять модуль другими способами. На этом сайте есть действительно хорошая статья о модулях javascript

2. Это хорошо, но я получаю сообщение об ошибке — jsfiddle.net/rjFHB или, возможно, я инициализирую модуль. Пользователи в неправильном направлении.

3. Это была моя ошибка — «Модуль. Пользователи»не должны иметь var перед ним (поскольку глобальный модуль уже определен). Я отредактирую это.

Ответ №2:

Первый шаблон допускает использование частных переменных, методов и т. Д. Через замыкания. Например:

 var MODULE = (function () {

    var privateStuff = 'This is private';

    var doStuff = function(obj) {
        console.log('Doing stuff...');
        console.log(privateStuff);
    };

    return {
        common: {
            init: function() {
                console.log("common.init");
                doStuff(this);
            }
        },
        users: {
            init: function () {
                console.log("users.init");
            },
            show: function () {
                 console.log("users.show");
            }
        }
    }
})();
  

privateStuff и doStuff не являются свойствами объекта и не доступны ни для чего, кроме того, что определено внутри возвращаемой функции MODULE . Итак, показать пример того, как это сделать с помощью # 2, невозможно.

В JS нет понятия закрытых членов, поэтому вы не можете определить их через обычный объектный литерал. Так что, если вам нужны личные вещи, выбирайте первый вариант. Однако, если вы этого не сделаете, # 2 проще.

Ответ №3:

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