Giorgi Moniava
Giorgi Moniava

Reputation: 28654

Javascript object lost constructor when the prototype was changed

In below code

var A = function() {};
var a = new A();
var b = new A();

A.prototype = {};

var c = new A();
console.log(a.constructor === b.constructor);
console.log(a.constructor === c.constructor);

output is true and false.

I am interested in the false output. a and c were created using same constructor function which is A - why is their constructor property different? It seems I miss something.

PS. If I remove the line where I am changing prototype of A output is: true true.

Upvotes: 4

Views: 816

Answers (3)

Ming Huang
Ming Huang

Reputation: 1370

When using function as an object constructor, its prototype.constructor is automatically created with function's property. So initially after setting up the A function you will have a constructor in A's prototype:

A.prototype.constructor

So when you assign A.prototype ={}, you lost that original constructor in A.prototype.

You may fix it with adding this after A.prototype ={} line

A.prototype.constructor = A;

Both console should log true

Upvotes: 0

Mihai Alexandru-Ionut
Mihai Alexandru-Ionut

Reputation: 48367

The problem is that when you use A.prototype={} it is changed the behavior of A object.

When you use A.prototype={}, A object lost it’s constructor.

Why it is this behavior ?

The constructor property is assigned to prototype function.

And in your case ,A.prototype is replaced with a new Object {}, which doesn't have constructor property as own property (but its prototype has and is equal to Object).

Lets see the following example:

function A() { } // (1)
A.prototype = {}  // (2)

Before (2)

Object.prototype
{
    constructor:Object
}

A.prototype
//was autocreated with A
{
    constructor:A
}

After (2)

Object.prototype
{
    constructor:Object
}

A.prototype
//reassigned with {}
{
   //no constructor
}

Upvotes: 3

georg
georg

Reputation: 214959

When you construct an object, the constructor's prototype property is copied to the new object's __proto__, so while a and b retain the old prototype (which also contains the .constructor property), c uses the new blank prototype (which doesn't have constructor as own property). Here's a diagram:

After a = new A; b = new A:

enter image description here

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

enter image description here

As you can see, direct assignment to a prototype breaks the JS object system and may lead to surprising results (which your very question demonstrates). That's why it's generally frowned upon.

Upvotes: 4

Related Questions