Search code examples
javascriptconstructorprototype-programming

Intriguing behavior when set prototype on Constructor in javaScript


Begin with an simple attempt, I defined an Constructor and used it to create an instance myobject:

function MyConstructor () {};
var myobject = new MyConstructor ();

Then, I modified the prototype property of this Constructor and created another instance myobject1 with it:

MyConstructor.prototype = {};
var myobject1 = new MyConstructor ();

I repeated the same procedure and created another instance myobject2:

MyConstructor.prototype = {name: '2'};
var myobject2 = new MyConstructor ();

Now I am testing the constructor property of each instance, which is not what I expect:

myobject.constructor == MyConstructor;
//true
myobject1.constructor == MyConstructor;
//false
myobject2.constructor == MyConstructor;
//false

When looking up the [[prototype]], it is different from each other.

myobject.__proto__ == myobject1.__proto__
//false
myobject2.__proto__ == myobject1.__proto__
//false

Could anyone explain what happens to MyConstructor when changing its prototype property?


Solution

  • When you creating constructor:

    function MyConstructor() {};
    

    it has prototype.constructor set to MyConstructor:

    MyConstructor.prototype.constructor === MyConstructor; //true
    

    When you overwrite prototype of MyConstructor by

    MyConstructor.prototype = { foo: function () {} };
    

    then origignal MyConstructor.prototype object is replaced by passed object { foo: function () {} } and this object does not have property 'constructor' set to MyConstructor but to function Object because Object is constructor bound to all object created by object literals.

    So after this:

    MyConstructor.prototype = { foo: function () {} };
    MyConstructor.prototype.constructor === Object;
    

    and when you create new object with this constructor

    var foo = new MyConstructor();
    

    then:

    foo.constructor === Object; // true
    

    so to repair this problem, after you overwrite prototype then you have to correct constructor field:

    MyConstructor.prototype = { foo: function () {} };
    MyConstructor.prototype.constructor = MyConstructor;
    

    and then your constructor has prototype with correct constructor field. You could also write:

    MyConstructor.prototype = { foo: function () {}, constructor: MyConstructor };
    

    and final effect will be the same.