简体   繁体   中英

Differences between these two module patterns

Are there any differences in functionality between these two JavaScript module patterns?

var MODULE = (function() {

    var privvy = "I'm private!";

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

and

var MODULE = (function() {

    var privvy = "I'm private!";

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

I think what is happening is, in the first, an object with two public members is explicitly declared and then returned. One of the members has a function as a value which has a reference to the 'private' variable (ie a closure is formed by the immediately-executed function but the getPublic() method still has access to this variable after this function finished execution - I think)

In the second, an object is created by way of an anonymous constructor which assigns two functions to publicly accessible variables and the IEF creates the closure that limits access to the priv variable in the same way.

Do these two variations result in exactly the same object?

They're no different functionally. The MODULE object will work the same either way, but the first is preferred because the syntax is cleaner. No need for new and this .

JSLint corroborates this. With the second pattern, it complains about return new function() { being a "weird construction".

EDIT: As @zzzzBov and @Bergi pointed out, there is a difference regarding the object's prototype. Please see their answers for a detailed explanation.

The two versions are ever-so-slightly different. For reference I've added simple examples of the basic formats ( Version A & Version B ). There's not a significant difference in functionality, however Version B adds an additional layer of scope:

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

Additionally, the prototype of the object returned in Version A will be Object.prototype , whereas in Version B the prototype will be the anonymous function's prototype.

This difference can be seen by checking the module's __proto__ property against Object.prototype .


Version A is essentially shorthand for:

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

Version B is essentially shorthand for:

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

Version A

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

Version B

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

There's no big difference in the result, except the object from the second example has a (unenumerable) prototype property "constructor" pointing to that anonymous function. That means, you could create a copy of it with new MODULE.constructor .

When creating a singleton object, the first syntax is preferred. The second example is usually used without the new keyword, returning the constructor as MODULE so that you can create instances of it, having access all to the same ("static") priv variable.

You could throw in another pattern with a similiar result:

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

It would behave more like your first example, but leak a constructor which creates new priv variables instead of sharing the static one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM