Javascript'正常'对象与模块模式

Javascript 'normal' objects vs module pattern

本文关键字:模块 模式 正常 Javascript 对象      更新时间:2023-09-26

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

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

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

除了稍微复杂一点之外,没有什么缺点。您只需要获得更多的组织和封装选项。

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

如果每页只使用一个实例,我认为没有必要涉及new关键字。所以就我个人而言,我会像您在上一个示例中所做的那样创建一个揭示模块,并公开一个具有"public"属性的对象。

虽然我看不出你对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'

在你的问题中有几个概念被混为一谈

使用您所称的"普通对象",该函数将成为构造函数,并需要新的关键字。

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

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

function LoginModel(){
    var _notifyListeners = function(){ 
        // Do your stuff here
    };
    this.model = new MyModel();
    this.getModel = function(){
        _notifyListeners();
        return this.model;
    };
}

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