1

consider a piece of code

function F(){
   this.p=10;
}
F.prototype.newProp='some value';
var f1=new F(), f2=new F();

alert(f1.__proto__==f2.__proto__); //returns true. implies f1 and f2 share same instance of prototype object 

f1.newProp='new value'; //changing the value of inherited property
alert(f2.newProp); //returns 'some value' 

Ok now the question is if f1 and f2 both share the same [[prototype]] object instance and if property retrieval in javascript works by walking along the prototype chain

So if I change value of a property (newProp, in this case) of a shared [[prototype]] object, how come its not reflected in f2 as well , since f1.proto==f2.proto (which means its the SAME object) then why changing the newProp of f1 doesn't change newProp of f2 (both inherit from same prototype object, no ?)

Surprisingly,changing f1.proto.newProp reflects the change when retrieving "f1.newProp"

So , are f1.newProp and f1.proto.newProp different properties ?

I thought the property look up in javascript worked by successively looking higher in the prototype chain.

I am sorry if my question sounds naive, but I couldn't get my head around :

If 1) f1.proto==f2.proto //true! implies both objects f1 and f2 refer same [[prototype]] object from which they inherit

and if

2) property not found in object is searched in its prototype .

then why changing f1.newProp doesn't reflect in f2.newProp too ? as both have common [[prototype]] property as shown in point (1)

Is it that properties from prototype object are being copied individually into f1 and f2. ? but then thats in violation of point (2) [looking up the properties of prototype chain when not not found in the object]

Please explain the contradiction here. thank u very much :)

==================EDIT================

thank you @jfriend00 for the reply.

but lets say I have this code

function Person(name, age){      
    this.name=name;
    this.age=age;
    alert("obj created:"+name);
}
function Employee(name,age,eid){
    this.base=Person;
    this.base(name,age);
    this.eid=eid;
}
Employee.prototype=new Person;

var ob1=new Employee('name1',23,100);
var ob2=new Employee('name2',24,101);

here too, obviously ob1.proto==ob2.proto but if I am not mistaken there's 2 objects here for each instance of employee

1 is the employee object itself with only 1 property eid (and other one base func)

2nd is the Person object which is referenced by the [[prototype]] property of employee object. This object has name and age property.. So , employee obj actually stores and retrieves name and age from its [[prototype]] Person object. Am I right ?

If so , and since ob1.proto==ob2.proto, then how are we able to store unique name and age of both objects ?

I mean, here it almost seems there's a prototype object for each employee. if u could explain this, thank u very much :)

and one more query is :

how come the above code will work even if comment out the

Employee.prototype=new Person;

in the above line and thereby breaking the link between 2 objs. Inheritance still works just because I have declared Person function as a property of Employee and called Person from it . how is this working thank you :)

Sarabjeet
  • 264
  • 2
  • 17
  • On your additional code, you need to call the base object constructor from the derived object constructor so it can do its proper initalization work on the newly created object `Person.call(this, name, age);`. I don't know what reference you're learning form, but any good reference on inheritance in Javascript should show you this so it's probably in whatever reference you're using. – jfriend00 Nov 20 '14 at 07:25
  • ok, but can u please explain my original question of the edited part. How does ob1 and ob2 share same prototype object but yet both have different name and age properties , which are themselves stored in prototype object. thanks – Sarabjeet Nov 20 '14 at 07:31
  • Which question is that? You've asked a lot of questions and I don't know which one you still want help with. The prototype is only needed if you're actually using anything on it. If you aren't using it, then you don't have to set it because it doesn't have anything in it anyway. – jfriend00 Nov 20 '14 at 07:38
  • I was talking about the code snippet in my edited part. ob1 and ob2 have same prototype object. The prototype object stores 'name' and 'age' property , right ? if prototype object is same for both ob1 and ob2 , then how are ob1 and ob2 able to store unique 'name' and 'age' in 2 different objects ? I hope you understood my question. thanks – Sarabjeet Nov 20 '14 at 07:48
  • Its best not to create an instance of Parent to set as prototype of Child. How prototype properties are used, set, mutated and shadowed and how to inherit is explained in detail here: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Nov 20 '14 at 08:05

2 Answers2

1

The prototype object is shared among all objects (as you have shown).

But, when you assign to a property an the object, it doesn't change the prototype, the property goes on the object itself and because of the lookup order for resolving a property reference, the newly assigned property on the object itself is found before the one on the prototype so it becomes the active property.

When you reference a property on an object, there is a search order. First it looks for properties directly on the object. If no match is found, then it searches the prototype chain.

When you write to a property on the object, it never writes to the prototype unless you explicitly reference the prototype object, instead it puts a property directly on the object and that property then becomes the active one (essentially overriding what's on the prototype).

You can tell whether a property is on the object itself or on the prototype by using .hasOwnProperty(). That will return true only when the property is directly on the object.

So, in your code:

f1.newProp='new value'; //changing the value of inherited property

This adds a new property directly to the object (not on the prototype) and it essentially overrides what is on the prototype.


In general, data properties are usually set in the constructor to avoid any confusion about the two possible locations the property can reside and, if you're writing to them, there's really no advantage to having initially specified them on the prototype. Function properties (e.g. methods) are often set in the prototype because they generally aren't written to so it's more efficient to just have one shared prototype object that contains them that can be read from.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • thank you so much . but lets say I have this code `code` function Person(name, age){ this.name=name; this.age=age; alert("obj created:"+name); } function Employee(name,age,eid){ this.base=Person; this.base(name,age); this.eid=eid; } Employee.prototype=new Person; var ob1=new Employee('name1',23,100); var ob2=new Employee('name2',24,101); `code` // ob1.__proto__ == ob2.__proto__ is true – Sarabjeet Nov 20 '14 at 07:03
  • @Sarabjeet - multi-line code isn't readable in comments. You can use the edit link on your original post to put what you're asking about there and then post a comment to call attention to the new code. – jfriend00 Nov 20 '14 at 07:09
  • @Sarabjeet - you edit your own post with your additional code, not mine. – jfriend00 Nov 20 '14 at 07:20
  • sorry jfriend00 , I am new to this site . I have edited my post. – Sarabjeet Nov 20 '14 at 07:23
1

Once you set f1.newProp = 'new value', it no longer is setting newProp on the prototype, but on the f1 object itself. Try this, you will see:

var f1=new F(), f2=new F();
console.log(f1.hasOwnProperty('newProp')); // returns false, because it is from prototype
f1.newProp = 'new value';
console.log(f1.hasOwnProperty('newProp')); // returns true
deitch
  • 14,019
  • 14
  • 68
  • 96