开发者

javascript object literal pattern with multiple instances

I have developed a little javscript widget to turn some nested <ul> blocks into a windows explorer style browser. I have recently learnt about the object literal pattern and decided to give it a go, so the organisation of my code is something like this:

var myExplorer = {
    init : function(settings) {
        myExplorer.config = {
            $wrapper : $('#explorerCategories'),
            $contentHolder : $j('#categoryContent'),
            loadingImg : '<img src="../images/standard/misc/ajax_loader.gif" alt="loading" class="loading" />'
        }
        // provide for custom configuration via init()
        if (settings && typeof(settings) == 'object') {
            $.extend(myExplorer.config, settings);
        }

        // some more code...
    },

    createExpanderLink : function() {
        // mo开发者_StackOverflow社区re code
    },

    anotherMethod : function() {
        // etc
    }
}

Then in my page I set up my explorer with:

$j(function () {
    myExplorer.init();
}

This all works fine by the way. The problem is when I want to have more then one of these explorer style widgets on the same page. I tried passing in the different settings:

$j(function () {
    // first instance
    myExplorer.init();

    //second instance
    var settings = {
        $wrapper : $('#explorerCategories2'),
        $contentHolder : $j('#categoryContent2')
    }
    myExplorer.init(settings);

}

But this simply overwrites the config vales for the first instance which effectively breaks it. I'm beginning to realise that the object literal pattern isn't the way to go here but I'm not sure what is. Can anyone offer any pointers?


Use a function instead on an object literal, so you can instantiate multiple objects of the widget using the new keyword.

function myExplorer(settings) {
    // init code here, this refers to the current object
    // we're not using a global object like myWindow anymore
    this.config = {
        $wrapper : $('#explorerCategories'),
        $contentHolder : $j('#categoryContent'),
        ..
    };

    // provide for custom configuration
    if (settings && typeof(settings) == 'object') {
        $.extend(this.config, settings);
    }

    this.someFunction = function() { 
        ..
    };

    this.otherFunction = function() {

    };
}

Instantate as many objects of this widget as needed using,

var foo = new myExplorer({ .. });
var bar = new myExplorer({ .. });
...


What about this?

var myExplorer = function(settings) {

  var o = {
    init: function() {
      this.somevalue = settings;
    },

    whatever: function() {
    }
  };

  o.init();

  return o;
};

var exp1 = myExplorer('something');
var exp2 = myExplorer('anything');

console.log(exp1.somevalue); //something
console.log(exp2.somevalue); //anything


Use the following code to achieve this, remember about the 'public API' (so that the 'internal' function will be visible 'outside'):

var myExplorer = function() {
    var init = function(settings) {
        var config = {
            $wrapper : $('#explorerCategories'),
            $contentHolder : $j('#categoryContent'),
            loadingImg : '<img src="../images/standard/misc/ajax_loader.gif" alt="loading" class="loading" />'
        }
        // provide for custom configuration via init()
        if (settings && typeof(settings) == 'object') {
            $.extend(config, settings);
        }

        // some more code...
    },

    var createExpanderLink = function() {
        // more code
    },

    var anotherMethod = function() {
        // etc
    }

    // Public API 
    // return the functions you want to use outside of the current instance
    return {
        init : init,
        createExpanderLink : createExpanderLink,
        anotherMethod : anotherMethod
    }
}
var firstExplorer = new myExplorer();
var secondExplorer = new myExplorer();
// etc 


When you call $.extend() like this, it merges the second object's properties into the first:

$.extend(myExplorer.config, settings);

Instead, create a new object that's the result of the merge leaving the first object (the defaults) untouched, like this:

this.settings = $.extend({}, myExplorer.config, settings);

What this does is still merge the passed objects into the first, but the first is a new object ({}), so we're not affecting either of the others, then just use this.settings (or a different name to make it absolutely clear) inside your object.


From my understanding you are trying to create a new instance of object which was defined using object literal notation. object literals can be instantiated using Object.create method. Here is the code that explains how to instantiate an object from object literal notation.

            var objLiteral = {
                name:"kanthan",
                address:'',
                deliver:function(){
                    if(this.address){
                        console.log("Your product has been successfully delivered at "+this.address);
                    }
                    else{
                        console.log("please enter the address to deliver");
                    }
                }
            };
            var cum=Object.create(objLiteral);
            cum.address="gkm colony";
            objLiteral.deliver();
            cum.deliver();
            var cum1=objLiteral;
            cum1.address="gkm colony";
            objLiteral.deliver();
            cum1.deliver();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜