Search code examples
javascriptprototypedesign-patternsobject-create

Object.create and reference properties


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!


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();