Question

I've been doing some research on object literals and such. I am creating a game that has various properties from my player. These prorpeties are stored in multiple groups, such as his ship and all the properties for that, his wepaon and all the properties for that, etc..As a result I have been storing these properties into object literals.

I don't want my object values to be overwritten. I ran across an article here http://www.gabordemooij.com/jsoop.html, and curious if something like this would be a healthy start to keeping object values from easily being overwritten...

Cat = {
  createNew: function() {
    var cat = {};
    var sound = "meow"; //sound is local
    cat.makeSound= function(){
        //can reach sound from here
        alert( sound );
    }
    return cat;
  }
}

var cat = Cat.createNew();
cat.makeSound();
//but can't reach sound from here
alert(cat.sound); //fail!
Was it helpful?

Solution

I've set up a small test in jsFiddle to demonstrate how the Revealing Object Pattern is a wonderful thing:

var Test = (function(){
    var priv = "Banana";
    var public = "Orange";
    var pubobj = {name:"Cheese"};

    function constructor(){
        this.public = public;
        this.pubobj = pubobj;

        this.instance = {name:"Grape"};

        this.instanceMethod = function(){
            return priv;
        };
    };

    constructor.prototype.private = function(){
        return priv;
    };            

    return constructor;

})();

var myTest = new Test();

console.log(myTest.public);     //Orange
console.log(myTest.priv);       //undefined
console.log(myTest.private());  //Banana

var myTest2 = new Test();

console.log(myTest.public === myTest2.public);    //true (they are both primitives with the same value)
console.log(myTest.private === myTest2.private);  //true (the methods share the same instance)

myTest.public = "cheese";
console.log(myTest.public, myTest2.public);       // "cheese", "Orange" (overwriting the primitive doesn't change the primitive of myTest2)

myTest.pubobj.name = "Melon";                   
console.log(myTest.pubobj, myTest2.pubobj);       //the name property for both is now "Melon" (both test objects share the same instance of pubobj)

myTest.instance.name = "Raspberry";
console.log(myTest.instance, myTest2.instance);  // the name of myTest2.instance is unchanged

console.log(myTest.instanceMethod === myTest2.instanceMethod);​  // false (while identical, these methods have separate instances)

OTHER TIPS

It fails because sound is a local variable which can not be referenced outside of the object.

If you want to reference it, you need to make a getter.

Cat = {
  createNew: function() {
    var cat = {};
    var sound = "meow"; //sound is local
    cat.getSound= function(){
        //can reach sound from here
        return sound;
    }
    return cat;
  }
}


var cat = Cat.createNew();
alert(cat.getSound());

or

Cat = {
  createNew: function() {
    var cat = {};

    var props = {
        sound : "meow",
        foo : "bar"
    };

    cat.get= function(key){            
        return props[key];
    }
    return cat;
  }
}

var cat = Cat.createNew();
alert(cat.get("sound"));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top