3

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!

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Raphael
  • 1,847
  • 1
  • 17
  • 29
  • 1
    Create a constructor method that returns a fully qualified object with a copy of the array. – TheZ Oct 16 '12 at 20:03
  • 1
    Reference types will have this problem. You simply need to somehow manually put reference types directly on the object instead of on the prototype. – I Hate Lazy Oct 16 '12 at 20:28
  • Here, the learning is always put functions in the prototype object and the properties(each instance is likely to have separate copy) in the constructor. – kshirish Nov 29 '14 at 15:05

3 Answers3

3

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();
JasonWyatt
  • 5,275
  • 1
  • 31
  • 39
  • 1
    `Object.create` wouldn't work with the array parameter, because you'd still only be creating a new object with a *reference* to the array, as opposed to a new array. – JasonWyatt Oct 19 '12 at 13:39
  • 1
    That's sad... it would be much nicer to create classes and objects with fewer lines =/ – Raphael Oct 19 '12 at 14:06
2

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());
Travis J
  • 81,153
  • 41
  • 202
  • 273
  • Your use of `this` isn't quite right. Some of your methods are using `this` instead of referencing the local variables. – I Hate Lazy Oct 16 '12 at 20:33
-1

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"]​
Dcullen
  • 669
  • 4
  • 11