Object.prototype.constructor做什么?

时间:2012-05-31 14:56:16

标签: javascript

假设我们有这个构造函数:

var Foo = function(){
   this.x = "y";
}

FooFoo.prototype.constructor评估相同的功能,但Foo.prototype.constructor = function(){this.x="z"}似乎没有更改new Foo()的结果。但它会改变

的结果
var i = new Foo();
i.constructor; // evals to function (){this.x = "z"}

这里发生了什么?我不打算使用来做任何事情,我只是对这种语言感到好奇。

2 个答案:

答案 0 :(得分:3)

函数的constructor属性的prototype属性旨在指向函数,以便您可以向对象询问构造它的内容。它是作为更新功能对象的一部分自动设置的(参见规范的Section 13.2)。如您所见,您可以覆盖constructor上的Foo.prototype属性,如果您愿意,可以更改它,但默认情况下就是它的用途。

有一个很好的理由可以覆盖它,这与继承有关。假设您希望拥有一个用于创建基础对象的Base构造函数,以及一个Derived构造函数,该构造函数用于创建具有Base特征以及Derived的添加/修改的派生对象。通常(虽然不是我的想法)你看到完成(没有帮助脚本)的方式是:

function Base() {
}
Base.prototype.foo = function() {
    console.log("I'm Base#foo");
};

function Derived() {
}
Derived.prototype = new Base(); // So we get all the `Base` stuff
Derived.prototype.bar = function() {
    console.log("I'm Derived#bar");
};

var d = new Derived();
d.foo(); // "I'm Base#foo"
d.bar(); // "I'm Derived#bar"

现在的问题是,d.constructor === Base而不是Derived。所以能够解决这个问题很重要:

...
Derived.prototype = new Base();          // So we get all the `Base` stuff
Derived.prototype.constructor = Derived; // Fix up
...

(旁注:所有这些管道 - 以及围绕超级调用的复杂性 - 是为什么这么多人为此创建了帮助脚本的原因,包括(咳嗽) mine。)


请注意,上述内容并不是设置继承层次结构的理想方法。这是你经常看到的,但正如我上面所说,并不理想。为了完整起见,这更好:

function Base() {
}
Base.prototype.foo = function() {
    console.log("I'm Base#foo");
};

function Derived() {
    Base.call(this); // So Base sets up its stuff
}
Derived.prototype = Object.create(Base.prototype); // So we get all the `Base` stuff
Derived.prototype.bar = function() {
    console.log("I'm Derived#bar");
};

var d = new Derived();
d.foo(); // "I'm Base#foo"
d.bar(); // "I'm Derived#bar" 

...在ES5之前的环境中,您使用垫片/填充物Object.create。但同样,我不直接这样做(并且不推荐它),我使用帮助脚本,因此它是声明性的和可重复的。

答案 1 :(得分:2)

.prototype.constructor只是一个辅助属性,因此创建的对象可以轻松地使用this.constructor引用构造函数,或者像i.constructor一样。

将其任意设置为其他内容并没有任何效果,除了期望获取具有obj.constructor的对象的构造函数的代码:

if( obj.constructor === Foo ) {
 //It's a Foo
}

因此,留下它是一个很好的惯例。

es5shim依靠.constructor.prototype来填充Object.getPrototypeOf