Object.create and reference properties
-
07-07-2021 - |
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!
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());
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"]