Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why changing the prototype does not affect previously created objects?

I have the following code:

var A = function() {};
var a = new A();
var b = new A();
A.prototype.member1 = 10;

A.prototype = {}
var c = new A();
console.log(a.member1);
console.log(a.constructor === b.constructor);
console.log(a.constructor === c.constructor);
console.log('---------');
console.log(c.member1);

It's output is:

10
true
false
---------
undefined
undefined

The prototype of a and b has not changed and c had a new one. Am i right that this was caused by the fact that a.constructor is not equal to c.constructor and each of them had own prototype? Are there any other circs when constructors of two objects might not be equal?

Extra question: why there were printed two undefined strings? (Chromium)

like image 656
Adam Sznajder Avatar asked Aug 22 '12 19:08

Adam Sznajder


3 Answers

At the time you're calling

var a = new A();

basically this assignment is done:

a.__proto__ = A.prototype;

Then you reassign the A.prototype to a new object, so c gets {} as its prototype.

A.prototype = {};
var c = new A();

However, this doesn't destroy the old A.prototype object - a.__proto__ is still pointing to it.

Am i right that this was caused by the fact that a.constructor is not equal to c.constructor and each of them had own prototype?

.constructor is basically just a convenience property. It has no effect on how instances behave.

Extra question: why there were printed two undefined strings?

Not in my console, they don't! (Opera 12)

like image 169
Imp Avatar answered Sep 20 '22 12:09

Imp


When you create an object, the prototype of the constructor is assigned to the __proto__ property of the new object. You're then changing the prototype, but the two a and b objects are already pointing at the original reference:

var a = new A();
// a.__proto__ == A.prototype == {} (soon == {member1:10})
var b = new A();
// b.__proto__ == A.prototype == {} (soon == {member1:10})

A.prototype = {} // this changes A.prototype, but not a.__proto__ or b.__proto__
var c = new A(); // c.__proto__ = {}

your first undefined is from c.member1. The 2nd one is chrome saying your entire statement had no return value

like image 42
Nobody Avatar answered Sep 19 '22 12:09

Nobody


The answer lies in this line of your code:

A.prototype = {}

When you get to this line of code, you are actually creating a BRAND NEW OBJECT in memory that is {}. Creating any new objects using A as your constructor will point to this BRAND NEW OBJECT as the prototype.

However, the OLD PROTOTYPE still exists in memory. It's just that A.prototype no longer points to it. Any objects you create using A as the constructor before you redefine A's prototype reference are still pointing to this OLD PROTOTYPE as it's prototype.

like image 44
David Nguyen Avatar answered Sep 20 '22 12:09

David Nguyen