Question

How do you deal with the problem of sharing a prototype's reference property among its children? Is there any well-known pattern (other then redefining the property inside the constructor) to solve this problem? Is this a problem at all, or there is something about prototype inheritance that I am missing?

Example:

var dog = 
{
    name: "no-name",
    paws: ["front-right", "front-left", "back-right", "back-left"]
};

var rex = Object.create(dog);
rex.name = "Rex";

var bingo = Object.create(dog);
bingo.name = "Bingo";
bingo.paws.pop(); //Bingo is just like a dog, but has lost a paw in a tragic accident

console.log(bingo.paws); //["front-right", "front-left", "back-right"]
console.log(rex.paws); //Rex lost a paw too! ["front-right", "front-left", "back-right"]


UPDATE:

After studying about prototype-inheritance, it seems to me that the "natural" way of programming in this paradigm is by extending objects, and not relying too much on constructors in the sense of using them as "classes". The example I've seen on a blog (and its also seems to be in agreement with Douglas Crockford's Object.create) was more or less like this:

var Dog = 
{
    name: "no-name",
    paws: ["front-right", "front-left", "back-right", "back-left"],
    bark: function() { alert("Bark!!"); }
};

//No constructor acting like a "class"
var BigDog = Object.create(Dog);
BigDog.bark = function() { alert("WOLF!!!"); };

var thor = Object.create(BigDog);
thor.name = "Thor";
thor.bark();

Are constructors the only way of copying or creating a new array on the new instance? Is this pattern of Object.create "incomplete"?

Thanks for the answers!

Was it helpful?

Solution

As you already know, the prototype of an object is an object containing the base properties which make up that object. That prototype object is, like all objects, a mapping of names to values. Arrays (and objects) in javascript are always passed by reference, so when Object.create is called on the prototype - it's only copying the reference of the array into the new object. As TheZ stated in his comment, you could do something like this:

function Dog(){
    this.paws = ['front-right', 'front-left', 'back-right', 'back-left'];
}
Dog.prototype = {
    name: 'no-name',
    paws: null
};

So now we can create our objects:

var rex = new Dog();
rex.name = 'Rex';

var bingo = new Dog();
bingo.name = 'Bingo';
bingo.paws.pop();

OTHER TIPS

You should look into the module pattern

Make a closure that gets used so your dogs can be separate

var dog = function(){
 //private
 var name = "no-name";
 var paws = ["front-right", "front-left", "back-right", "back-left"];

 //public
 function getName(){
  return name;
 }

 function setName(newName){
  name = newName;
 }

 function getPaws(){
  return paws;
 }

 function pawPain(){
  paws.pop();
 }

 //expose
 return{
  pawPain: pawPain,
  getPaws: getPaws,
  getName: getName,
  setName: setName
 };
};

Now you can use this to make new dogs

var rex = new dog();    
var bingo = new dog();
rex.pawPain();
console.log(bingo.getPaws());

http://jsfiddle.net/sVaSp/

Just need a constructor. Each version holds its own copy of the object.

    function dog(name) {
        this.name = "no-name",
        this.paws = ["front-right", "front-left", "back-right", "back-left"]
    } 

    var rex = new dog();
    rex.name = "Rex";

    var bingo = new dog();
    bingo.name = "Bingo";
    bingo.paws.pop(); //Bingo is just like a dog, but has lost a paw in a tragic accident

    console.log(bingo.paws); //["front-right", "front-left", "back-right"]
    console.log(rex.paws); //Rex lost a paw too! ["front-right", "front-left", "back-right"]​
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top