这种定义JS对象的方式有什么用处吗?

我维护一些遗留代码,我注意到使用下面的定义对象的模式:

var MyObject = {}; (function (root) { root.myFunction = function (foo) { //do something }; })(MyObject); 

这有什么目的吗? 这相当于只是做了以下几点?

 var MyObject = { myFunction : function (foo) { //do something }; }; 

我并不打算进行一个神圣的探索来重构整个代码库,但是我真的很想理解这个迂回的定义对象的原因。

谢谢!

它被称为模块模式http://toddmotto.com/mastering-the-module-pattern/

主要的原因是你创build真正的私人方法和variables。 在你的情况下,它没有意义,因为它没有隐藏任何实现细节。

下面是一个使用模块模式的例子。

 var MyNameSpace = {}; (function(ns){ // The value variable is hidden from the outside world var value = 0; // So is this function function adder(num) { return num + 1; } ns.getNext = function () { return value = adder(value); } })(MyNameSpace); var id = MyNameSpace.getNext(); // 1 var otherId = MyNameSpace.getNext(); // 2 var otherId = MyNameSpace.getNext(); // 3 

而如果你只使用了一个直线对象,那么addervalue就会公开

 var MyNameSpace = { value: 0, adder: function(num) { return num + 1; }, getNext: function() { return this.value = this.adder(this.value); } } 

你可以通过做类似的东西来打破它

 MyNameSpace.getNext(); // 1 MyNameSpace.value = 0; MyNameSpace.getNext(); // 1 again delete MyNameSpace.adder; MyNameSpace.getNext(); // error undefined is not a function 

但是与模块版本

 MyNameSpace.getNext(); // 1 // Is not affecting the internal value, it's creating a new property MyNameSpace.value = 0; MyNameSpace.getNext(); // 2, yessss // Is not deleting anything delete MyNameSpace.adder; MyNameSpace.getNext(); // no problemo, outputs 3 

目的是限制闭包内的函数的可访问性 ,以防止其他脚本在其上执行代码。 通过将它封装在闭包中,您将重新定义闭包 的所有代码的执行范围 ,并有效地创build一个私有范围。 看到这篇文章的更多信息:

http://lupomontero.com/using-javascript-closures-to-create-private-scopes/

从文章:

JavaScript中最为人所知的问题之一就是它依赖于全局范围,这基本上意味着你在一个函数之外声明的任何variables都存在于同一个名字空间中:不祥的窗口对象。 由于网页的性质,来自不同来源的许多脚本可以(并且将)在共享全局范围的相同页面上运行,这可能是非常糟糕的事情,因为它可能导致名称冲突(名称相同的variables被覆盖)和安全问题。 为了尽量减less这个问题,我们可以使用JavaScript的强大的闭包来创build私有的范围,我们可以确定我们的variables对页面上的其他脚本是不可见的。


码:

 var MyObject = {}; (function (root) { function myPrivateFunction() { return "I can only be called from within the closure"; } root.myFunction = function (foo) { //do something }; myPrivateFunction(); // returns "I can only be called from within the closure" })(MyObject); myPrivateFunction(); // throws error - undefined is not a function 

Adavtages:

1,第一个模式可以作为一个模块,它接受一个对象并且修改一下这个对象。 换句话说,你可以定义这样的模块如下

 var module = function (root) { root.myFunction = function (foo) { //do something }; } 

并使用它:

 var obj = {}; module(obj); 

所以这个模块的优点是可以重复使用的。


2 。 在第一种模式中已经提到过其他的答案,你可以定义一个私有的作用域来存储你的私有属性,例如私有属性和方法。 例如,考虑这个片段代码

 (function (root) { // this plays as a private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(MyObject); 

3 。 另一个好处是可以使用这个模式来为所有types的对象(如数组,字面对象,函数)添加一个方法或属性

 function sum(a, b){ return a + b; } (function (root) { // this plays as a private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(sum); console.log(sum(1, 2)); // 3 console.log(sum.multiply(4)); // 12 

注:在我看来,主要优势可能是第二个(创build一个私人范围)

优点:

  1. 保持私人范围内的variables。

  2. 您可以扩展现有对象的function。

  3. 性能提高。

我认为上述三个简单的观点就足以遵循这些规则。 为了保持简单,除了编写内部函数外,

在您展示的特定情况下,在function或可视性方面没有任何意义上的差异。

原来的编码人员很可能采用这种方法作为一种模板,允许他定义私有variables,这些私有variables可以用于像myFunction这样的事物的定义:

 var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; // <-- private variable root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject); 

这样可以避免每次调用函数时计算seconds_per_day ,同时避免污染全局范围。

然而,没有什么本质上的不同,只是说

 var MyObject = function() { var seconds_per_day = 24 * 60 * 60; return { myFunction: function(foo) { return seconds_per_day; } }; }(); 

原始的编码器可能更希望能够使用root.myFunction = function的声明性语法而不是myFunction: function的对象/属性语法向对象添加myFunction: function 。 但是这种差异主要是一个偏好的问题。

然而,原始编码器所采用的结构的优点是,可以在代码中的其他地方容易地添加属性/方法:

 var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject); (function(root) { var another_private_variable = Math.pi; root.myFunction2 = function(bar) { }; })(MyObject); 

总之,如果你不需要,不需要采用这种方法,但是也不需要改变,因为它工作的很好,而且实际上有一些优点。

此模式提供了一个范围,您可以在其中定义在全局范围内不可见的帮助函数:

 (function (root) { function doFoo() { ... }; root.myFunction = function (foo) { //do something doFoo(); //do something else }; })(MyObject); 

doFoo是匿名函数的本地,它不能从外部引用。