1

I have read a lot on how prototypal inheritance works and how the interpreter travels the prototype chain to find the property.

function Man()
{
    this.hands=2;//1
}
function father()
{
    this.name="";
}
father.prototype= new Man();//2

var malay= new father();
var abhik= new father();

Now my question is that statement #1 & #2 is only invoked once . So "abhik" and "malay" should both share the same Man object ? So there will be 3 objects in memory . 1.abhik 2.malay 3.man (One instance shared by both) So by that logic the changed value should be shared across objects ?

malay.hands=3;
console.log(abhik.hands);
abhik.hands=4;
console.log(malay.hands);

But it is not the case. Why so ?

Abhik
  • 1,920
  • 7
  • 27
  • 50
  • For more info on how to subclass: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 Anything set to the something.prototype is shared among instances if your instance needs to subclass Man than in the function body of Father call Man in the context of the to be created Father like so: Man.call(this); – HMR May 23 '13 at 04:58
  • The moment you are setting the hands property on Malay you are covering the property, shadowed from the prototype.(sry for the formatting, mobile) – Moritz Roessler May 23 '13 at 04:59

2 Answers2

2

Your understanding is correct that there are 3 objects and both abhik and malay inherit from the same Man instance. But when you set new hands properties on the malay and abhik objects, you give them their own hands property and they are no longer inheriting the hands property from the prototype Man.

Illustration:

After you first create malay and abhik, here is a mock of your three objects:

father.prototype -> {hands: 2} 
malay -> {name: ""}   // Empty name property, NO hands property
abhik -> {name: ""}   // Empty name property, NO hands property

When you check for the hands property on malay or abhik, the interpreter will see that there is no such property and will check up the prototype chain and will find that their parent father.prototype does have a hands property, so the interpreter will report that value, which is 2.

After you set the hands properties, your objects look like this:

father.prototype -> {hands: 2} 
malay -> {name: "", hands: 3}   // Empty name property, OWN hands property
abhik -> {name: "", hands: 4}   // Empty name property, OWN hands property

Now your objects all have their own hands properties.

Resource: Here is a very well-written (but long) article about javascript inheritance: http://manuel.kiessling.net/2012/03/23/object-orientation-and-inheritance-in-javascript-a-comprehensive-explanation/

Dan
  • 59,490
  • 13
  • 101
  • 110
  • Any link explaining it in detail? . Does that mean every-time I call the new father(),new Man() will get invoked ? – Abhik May 23 '13 at 05:05
  • @Abhik posted a link in the comment. And no; a Man will only be created once. – HMR May 23 '13 at 05:10
  • No, the Man constructor is instantiated only once. Please see my updated answer. – Dan May 23 '13 at 05:15
1

If you need to share a primitive type or immutable among instances you can use closures to retain it's value and use getters and setters to access it.

function Man()
{
  var hands=2;
  return {
    getHands:function(){
      return hands;
    },
    setHands:function(number){
      hands=number;
    }
  }
}
function Father(name)
{
    this.name=name;
}
Father.prototype= Man();
malay=new Father("malay");
abhik=new Father("abhik");
malay.setHands(4);
console.log(abhik.getHands());
console.log(malay.getHands());

If you need Father to be an instance of Man you can do the following:

function Hands(){
  var hands=2;
  return {
    get:function(){
      return hands;
    },
    set:function(number){
      hands=number;
    }
  }
}

function Man(){
  this.age=18;
  this.array=[];
}
Man.prototype.hands=Hands();
function Father(name){
    //take ownership (copy) of every variable
    //defined in the Man function body
    //with this.... prototype defined
    //are still shared among instances
    Man.call(this);
    this.name=name;
}
Father.prototype= new Man();


malay=new Father("malay");
abhik=new Father("abhik");
malay.hands.set(4);
console.log(abhik.hands.get());
console.log(malay.hands.get());
malay.age=34;
console.log(abhik.age);//from Man.age
console.log(malay.age);//from malay.age
delete malay.age;
console.log(malay.age);//from Man.age
malay.array.push(22);
console.log(abhik.array);// is [] but would be [22]
 // if Man.call(this) was not in the Father function
console.log(malay instanceof Man);
HMR
  • 37,593
  • 24
  • 91
  • 160
  • I know the implementation . I just wanted to know the why and how . Still thanks anyway. – Abhik May 23 '13 at 09:49
  • The why is explained in a comment I gave 5 hours ago and sh0ber's answer. You can't directly assign a value to a property that is defined in an instance prototype. The how hasn't explained before as to how change value of "hand" prototype property. – HMR May 23 '13 at 10:57