Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is a.y undefined here?

function A() {}
A.prototype.x = 10;

var a = new A();
alert(a.x); // 10

A.prototype = {
  x: 20,
  y: 30
};

alert(a.y) // undefined
  1. Why does it delegate to old prototype of a.x and not the newer one?
  2. Why is a.y throwing undefined through it is set in prototype?
like image 532
Shane Avatar asked May 24 '15 20:05

Shane


3 Answers

This is happening because of when you've set A.prototype = obj

Rather than adding properties to the Object which is being inherited by a, you've created an entirely new object as A.prototype and this one isn't being inherited by a

Consider,

function A() {}
A.prototype.x = 10;

var p1 = A.prototype; // keep reference to this

var a = new A();

A.prototype = {x: 20, y: 30};

Object.getPrototypeOf(a) === A.prototype; // false, not the new prototype
Object.getPrototypeOf(a) === p1; // true, the old prototype

// however
var b = new A();
Object.getPrototypeOf(b) === A.prototype; // true, this is the new prototype

If you had made the changes to properties on the old prototype (which I called p1) these would have been seen inherited by a

like image 144
Paul S. Avatar answered Sep 21 '22 15:09

Paul S.


Why does it delegate to old prototype of a.x and not the newer one? Why is a.y throwing undefined through it is set in prototype?

You have created an entirely new prototype object. objects created already before the prototype property was changed will have the old reference and new objects will have new prototype.

// was before changing of A.prototype
a.[[Prototype]] ----> Prototype <---- A.prototype

// became after
A.prototype ----> New prototype // new objects will have this prototype
a.[[Prototype]] ----> Prototype // it will still reference to old prototype

The thumb rule is, prototype is set the moment of object's creation and later on you cannot change. It is possible only to add new or modify existing properties of the object’s prototype.

However, you can make a workaround with __proto__ property.

function A() {}
A.prototype.x = 10;

var a = new A();
alert(a.x); // 10

var _newPrototype = {
  x: 20,
  y: 30
};
A.prototype = _newPrototype; //will fail
alert(a.y) // undefined

A.__proto__ = _newPrototype; //will work
alert(a.x);
alert(a.y);
like image 29
Thalaivar Avatar answered Sep 18 '22 15:09

Thalaivar


You just created a new prototype object for the class "A", the old instance of the A

var a = new A();

...did copy the existing prototype object reference for it's instance. That old prototype -object is object of it's own and it is not destroyed because the instance of "A" is holding that reference.

If you want the "y" to be defined, you have to create the object again using new, the new instance would use the object you assinged for the prototype - and that instance has the "y" defined.

http://jsfiddle.net/ejseLum9/

like image 36
Tero Tolonen Avatar answered Sep 18 '22 15:09

Tero Tolonen