3

这两种 JavaScript 模块模式在功能上有什么不同吗?

var MODULE = (function() {

    var privvy = "I'm private!";

    return {
        getPublic: function() {
            return "I'm public";
        },      
        getPriv: function() {
            return privvy;
        }       
    };
}());

var MODULE = (function() {

    var privvy = "I'm private!";

    return new function() {
        this.getPublic = function() {
            return "I'm public";
        };
        this.getPriv = function() {
            return privvy;
        };
    };
}());

我认为首先,一个具有两个公共成员的对象被显式声明然后返回。其中一个成员具有一个作为值的函数,该函数具有对“私有”变量的引用(即,闭包由立即执行的函数形成,但 getPublic() 方法在该函数完成执行后仍然可以访问该变量 -我认为)

在第二种情况下,通过匿名构造函数创建一个对象,该构造函数将两个函数分配给可公开访问的变量,IEF 创建一个闭包,以相同的方式限制对 priv 变量的访问。

这两种变化是否会产生完全相同的对象?

4

3 回答 3

2

它们在功能上没有什么不同。无论哪种方式,该MODULE对象的工作方式都相同,但首选第一种方式,因为语法更简洁。不需要newthis

JSLint证实了这一点。对于第二种模式,它抱怨return new function() {是一个“奇怪的结构”。

编辑:正如@zzzzBov 和@Bergi 所指出的,对象的原型存在差异。请参阅他们的答案以获取详细说明。

于 2012-06-26T14:02:52.477 回答
2

这两个版本是非常不同的。作为参考,我添加了基本格式(版本 A版本 B)的简单示例。功能上没有显着差异,但是版本 B增加了一层范围:

var foo; //global scope
var module = (function () {
    var foo; //module scope
    return new function () {
        var foo; //inner scope
    };
}());

此外,在版本 A中返回的对象的原型将为Object.prototype,而在版本 B中,原型将是匿名函数的原型。

通过对照 .检查模块的__proto__属性Object.prototype可以看出这种差异。


版本 A本质上是以下的简写:

var module = (function () {
    var temp;
    temp = new Object();
    temp.foo = function () {...};
    return temp;
}());

版本 B本质上是以下的简写:

var module = (function () {
    function anon() {
        this.foo = function () {...};
    }
    return new anon();
}());

版本 A

var module = (function () {
    return {...};
}());

版本 B

var module = (function () {
    return new function () {...};
}());
于 2012-06-26T14:10:53.267 回答
2

结果没有太大区别,除了第二个示例中的对象有一个(不可枚举的)原型属性“构造函数”指向该匿名函数。这意味着,您可以使用new MODULE.constructor.

创建单例对象时,首选第一种语法。第二个示例通常不使用new关键字,返回构造函数,MODULE以便您可以创建它的实例,可以访问所有相同的(“静态”)priv变量。

您可以使用另一种具有类似结果的模式:

var MODULE = new function() {
    var priv = "I'm private!";
    this.getPublic = function() {
        return "I'm public";
    };
    this.getPriv = function() {
        return priv;
    };
}();

它的行为更像您的第一个示例,但泄漏了一个创建新priv变量而不是共享静态变量的构造函数。

于 2012-06-26T14:11:40.970 回答