How can I transition my Module-Singleton JavaScrip

2019-03-22 03:37发布

问题:

I've been writing an application and I have had a lot of success breaking different pieces of functionality into the so called "Module" pattern where you have a self-executing singleton with public and private members.

var WidgetModule = (function($, options) {

    // Private variable
    var someVar;

    // Private functions
    function somePrivateFunction() {

    }

    // Define the public members
    var self = {
        init: function() {

        },
        someFunction: function() {

        }
    };

    return self;

})(jQuery, options);

I have now run into a case where I have several modules which I would like to be able to create multiple instances of.

I know this pattern is based on the singleton but I wonder if there was a painless way to modify this pattern to support creating instances of them?

回答1:

When I need common functionality for multiple objects, here's the pattern I usually use (adjusted to account for the code you presented):

var Widget = (function($) {
    var pubs = Widget.prototype;

    // Private variable -- global to all instances
    var someVar;

    // The constructor    
    function Widget(options) {
        var privateInstanceVar;

        this.privateInstanceFunc = function() {
            return privateInstanceVar;
        };
    }

    // Private functions -- global to all instances
    function somePrivateFunction() {

    }

    // Define the public members
    pubs.init = function() {

    };

    pubs.someFunction = function() {

    };

    return Widget;

})(jQuery);

Usage:

var w = new Widget({someOption: "here"});

As you can see, you can share private data amongst all instances created by the constructor, and if you really want to, you can have private data that's shared only with certain select instance functions. Those functions have to be created in the constructor, which has reuse implications, whereas functions that don't need the truly-private instance data can be on the prototype and therefore be shared by all instances.

Better yet, since you already have a handy scoping function, you can help your tools help you by giving your public functions actual names:

    pubs.init = Widget_init;
    function Widget_init() {

    }

I mostly don't actually code the above, because I've defined a helper factory that makes it a bit more concise (and makes it easier to do specializations of functionality, like a Car inheriting functionality from Vehicle); details here.



回答2:

What about this:

function WidgetModule(options){
    //var $ = jQuery;
    // Private variable
    var someVar;

    // Private functions
    function somePrivateFunction() {

    }

    // Define the public members
    var self = {
        init: function() {
          console.log(options.id);
        },
        someFunction: function() {

        }
    };

    return self;
}

var w1 = WidgetModule({id:1}),
    w2 = WidgetModule({id:2});

w1.init(); // --> 1
w2.init(); // --> 2