新的JavaScript原型更改构造函数

时间:2014-06-20 21:06:01

标签: javascript constructor prototype

使用构造函数创建对象时,它具有指向构造函数的constructor属性:

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

创建此对象后,我可以更改Foo.prototype ...

Foo.prototype.x = 'y';

...或重新分配一个新的原型对象:

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

但是如果我在将新对象分配给Foo.prototype之后创建一个新的Foo对象,它的构造函数会突然指向Object

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

向原型添加新属性不会产生此效果,您必须执行作业Foo.prototype = {...}

我不知道为什么创建新原型会影响构造函数属性。我在Chrome,Firefox和Internet Explorer中测试过,结果相同。有人能帮我理解吗?

2 个答案:

答案 0 :(得分:1)

任何对象的constructor属性都是从该对象的原型继承的。

使用任何函数创建的默认prototype对象包含引用该函数的constructor属性,详见spec

您的新prototype对象没有该constructor属性,而是拥有自constructor继承自Object.prototype的{​​{1}}属性。

答案 1 :(得分:0)

总结一下:

  • myFoo.constructor实际上是myFoo.__proto__.constructor
  • 创建新原型不会影响现有对象。在上面的示例中,myFoo.x的值为"y",但myFoo.numundefined
  • 新创建的对象当然使用新原型,它没有属性constructor。因此他们继承了它。在上面的示例中,myBar.constructor实际上是myBar.__proto__.__proto__.constructor,指向Object

如果从对象文字中分配新原型,则只需设置构造函数属性:

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

或者更准确地说:

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