简体   繁体   中英

New JavaScript prototype changes constructor

When you create an object with a constructor it has a constructor property pointing to the constructor function:

var Foo = function(foo) {
    this.foo = foo;
}
var myFoo = new Foo(123);
myFoo.constructor === Foo; // true

After creating this object I can change Foo.prototype ...

Foo.prototype.x = 'y';

... or reassign a new prototype object:

Foo.prototype = {
    num: 99
};
myFoo.constructor === Foo; // still true

But if I create a new Foo object after assigning a new object to Foo.prototype its constructor suddenly points to Object :

var myBar = new Foo(321);
myBar.constructor === Foo; // false
myBar.constructor === Object; // wtf?!

Adding new properties to the prototype doesn't produce this effect, you have to do the assignment Foo.prototype = {...} .

I have no idea why creating a new prototype would affect the constructor property. I tested in Chrome, Firefox and Internet Explorer, all with the same result. Can anybody help me understand this?

The constructor property of any object is inherited from that object's prototype.

The default prototype object created with any function contains a constructor property that refers to that function, as detailed in the spec .

Your new prototype object doesn't have that constructor property, and instead has its own constructor property inherited from Object.prototype .

To sum it up:

  • myFoo.constructor is in fact myFoo.__proto__.constructor .
  • Creating a new prototype doesn't affect existing objects. In the example above, myFoo.x has the value "y" but myFoo.num is undefined .
  • Newly created objects use that new prototype, of course, which has no property constructor . Therefore they inherit it. In the example above, myBar.constructor is in fact myBar.__proto__.__proto__.constructor which points to Object .

If you assign a new prototype from an object literal you simply can set a constructor property:

var Foo = function(foo) {
    this.foo = foo;
};
var myFoo = new Foo(123);

Foo.prototype = {
    num: 99,
    constructor: Foo
};
var myBar = new Foo(99);

myBar.constructor === myFoo.constructor; // true

Or, more precisely:

Foo.prototype = {
    num: 99
};
Object.defineProperty(Foo.prototype, "constructor", {
    writable: true,
    configurable: true,
    enumerable: false,
    value: Foo
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM