Singleton pattern with Browserify/CommonJS

送分小仙女□ 提交于 2019-11-29 02:48:00

问题


Trying to implement the singleton pattern within CommonJS modules, using Browserify. So far:

// foo.js

var instance = null;

var Foo = function(){
    if(instance){
        return instance;
    }
    this.num = 0;
    return instance = new Foo();
}

Foo.prototype.adder = function(){
    this.num++;
};

module.exports = Foo();

// main.js

var foo = require('./foo.js');
console.log(foo.num); // should be 0
foo.adder(); // should be 1
var bar = require('./foo.js');
console.log(bar.num); // like to think it'd be 1, not 0

First problem is that I get a maximum call stack exceeded error when I load the built JS file in the browser, but secondly, am I approaching this correctly? Is this possible?


回答1:


First problem is that I get a maximum call stack exceeded error

Well, that comes from your Foo function recursively calling new Foo

but secondly, am I approaching this correctly?

No. For singletons, you don't need a "class" with a constructor and a prototype - there will only ever be one instance. Simply create one object, most easily with a literal, and return that:

module.exports = {
    num: 0,
    adder: function(){
        this.num++;
    }
};



回答2:


The result of any require call is a singleton -- whether a singleton instance or a singleton function or a singleton factory function. Furthermore, a require call should be idempotent -- poorly written CommonJS modules may violate this, so if a CommonJS module has a side effect, that side effect should happen only once no matter how many times that require is called.

The code snippet you have

if(instance){
    return instance;
}
// ...
return instance = new Foo();

is a legacy of the kinds of hoops you'd have to jump through if you were using plain old JavaScript to create singletons. It's totally unnecessary when using CommonJS and besides that, it leads to your maximum call stack exceeded issue.

Your code could be rewritten like this:

var Foo = function(){
   this.num = 0;
}

Foo.prototype.adder = function(){
   this.num++;
};

module.exports = new Foo();

or even more succinctly:

module.exports = {
   num: 0,
   adder: function(){ this.num++; }
}

because putting the adder method on the prototype doesn't gain you any real efficiency if you're only creating a single instance of Foo, and because you don't need to hide anything in the closure.



来源:https://stackoverflow.com/questions/24283362/singleton-pattern-with-browserify-commonjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!