【问题标题】:Javascript 'normal' objects vs module patternJavascript“普通”对象与模块模式
【发布时间】:2014-05-01 08:09:47
【问题描述】:

目前我正在开发一个大型 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
   };
});

【问题讨论】:

标签: javascript object-literal module-pattern


【解决方案1】:

模块模式更适合整体代码组织。它让您拥有该范围私有的数据、逻辑和函数。

在您的第二个示例中,getModel()唯一从外部获取模型的方法。除非显式公开,否则在模块中声明的变量是隐藏的。这可能是一件非常方便的事情。

除了稍微复杂一点之外,实际上并没有任何缺点。您只会获得更多的组织和封装选项。

我会使用一个普通的对象,直到我的模型变得复杂到需要更多的结构和一些私有范围。当你达到这一点时,将它重新定义为一个揭示模块而不破坏任何使用它的代码是微不足道的。

【讨论】:

  • +1 用于普通对象到模块的方法 - 这是一个很好的建议。
【解决方案2】:

如果您只打算每页使用一个实例,我认为没有必要使用 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);

})(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'

【讨论】:

  • 不可能同时接受这两个答案,但它们都很棒。我真的明白你们提到的观点并将代码切换为使用revealing module pattern!感谢您的帮助:)
【解决方案3】:

您的问题中有几个概念混为一谈

有了你所谓的“普通对象”,函数就变成了构造函数,并且需要 new 关键字。

第二个示例使用 IIFE 内部的显示模块模式。这是模块模式最流行的变体,但不幸的是存在严重缺陷。有关差异的解释,请参阅我的回答 here,有关其缺陷,请参阅 here

现在,您的问题提出了错误的二分法——普通对象还是模块模式?您不必做出选择——普通对象可以使用模块模式,只需将它想要保持私有的任何内容放在其闭包范围内即可。例如,

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

    this.model = new MyModel();

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

这是一个使用模块模式的“普通对象”示例。你必须避免做的是揭示模块模式所做的——将 everything 放入闭包范围。你应该只把你想要保密的东西放在闭包范围内。

【讨论】:

    猜你喜欢
    • 2016-12-21
    • 2023-03-07
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多