«Обычные» объекты Javascript против шаблона модуля

В настоящее время я разрабатываю крупномасштабное приложение Javascript (одностраничное), и я искал в Интернете несколько лучших практик. В большинстве проектов используется шаблон модуля, поэтому объекты не загрязняют глобальное пространство имен. В данный момент я использую обычные объекты:

function LoginModel(){
    this.model = new MyModel();

    this.getModel = function(){
        return this.model;
    };
}

Это читабельно и легко поддерживать (мое мнение). Лучше ли использовать шаблон модуля только из-за пространства имен или у него есть другие преимущества, о которых я не знаю (счетчик утечек памяти,...)? Кроме того, я уже разделил файлы, чтобы получить хороший шаблон MVC и уничтожить каждый объект, когда это необходимо (встречные утечки памяти). Итак, главный вопрос: нужно ли мне в моем случае использовать шаблон модуля или нет?

Шаблон модуля:

var LoginModel = (function(){
   var model = MyModel;

   function getModel(){
      return model;
   };

   return {
      getModel: getModel
   };
});

person GuyT    schedule 01.05.2014    source источник
comment
возможный дубликат почему шаблон модуля?   -  person thefourtheye    schedule 01.05.2014


Ответы (3)


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

Хотя я не вижу вашей точки зрения с функцией getModel(), поскольку MyModel, очевидно, доступен за пределами области видимости.

Я бы немного переписал:

var LoginModel = (function(model, window, undefined){

    function init(){ } // or whatever

    function doSomethingWithModel(){
        console.log(model);
    }

    return { init: init };

})(MyModel, window);

Если вы не уверены, какие модули получат model, вы можете использовать свободную аугментацию и изменить

})(MyModel, window);

to

})(MyModel || {}, window);

Если вам нужно несколько экземпляров модуля, это будет выглядеть примерно так:

var LoginModel = (function(model, window, undefined){

    function loginModel(name){ // constructor
        this.name = name; // something instance specific
    }

    loginModel.prototype.getName = function(){
        return this.name;
    };

    return loginModel;

})(MyModel, window);

var lm1 = new LoginModel('foo');
var lm2 = new LoginModel('bar');

console.log(lm1.getName(), lm2.getName()); // 'foo', 'bar'
person Johan    schedule 01.05.2014
comment
Невозможно принять оба ответа, но они великолепны. Я действительно понимаю, что вы оба упомянули и переключили код на использование revealing module pattern! Спасибо за помощь :) - person GuyT; 01.05.2014

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

Во втором примере getModel() является единственным способом получить модель извне. Переменная, объявленная в модуле, скрыта, если она явно не указана. Это может быть очень удобной вещью.

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

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

person Alex Wayne    schedule 01.05.2014
comment
+1 за подход простого объекта к модулю - отличное предложение. - person Johan; 01.05.2014

В вашем вопросе смешано несколько понятий

С тем, что вы называете «обычным объектом», функция становится функцией-конструктором и требует нового ключевого слова.

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

Теперь ваш вопрос представляет собой ложную дихотомию — обычные объекты или шаблон модуля? Вам не нужно делать выбор — обычный объект может использовать шаблон модуля, просто поместив все, что он хочет сохранить приватным, в свою область закрытия. Например,

function LoginModel(){
    var _notifyListeners = function(){ 
        // Do your stuff here
    };

    this.model = new MyModel();

    this.getModel = function(){
        _notifyListeners();
        return this.model;
    };
}

Это пример «нормального объекта», использующего шаблон модуля. Чего вам следует избегать, так это того, что делает шаблон раскрывающегося модуля — помещение всего в область закрытия. Вы должны помещать в область закрытия только то, что хотите сохранить в тайне.

person I-Lin Kuo    schedule 01.05.2014