anObject.prototype.constructor有什么作用? [英] What does anObject.prototype.constructor do?
问题描述
假设我们有这个构造函数:
Suppose we have this constructor:
var Foo = function(){
this.x = "y";
}
Foo
和 Foo.prototype.constructor
求值为同一个函数,但 Foo.prototype.constructor = function(){this.x =z}
似乎没有改变 new Foo()
的结果。但它会改变结果
Foo
and Foo.prototype.constructor
evaluate to the same function, yet Foo.prototype.constructor = function(){this.x="z"}
doesn't seem to change the result of new Foo()
. It does however change the result of
var i = new Foo();
i.constructor; // evals to function (){this.x = "z"}
这里发生了什么?我不打算使用这个用于任何事情,我只是对这种语言感到好奇。
What's going on here? I don't plan on using this for anything, I'm just curious about the language.
推荐答案
函数的 prototype
属性的构造函数
属性旨在指向函数,以便您可以问一个对象是什么构造它的。它作为创建功能对象的一部分自动设置(参见第13.2节规范)。如您所见,您可以覆盖 Foo.prototype
上的构造函数
属性,如果您愿意,可以更改,但默认情况下就是它的用途。
The constructor
property of the prototype
property of a function is meant to point back to the function so that you can ask an object what constructed it. It's set up automatically as part of creaeting the function object (See Section 13.2 of the spec). As you've seen, you can override the constructor
property on the Foo.prototype
if you like, to change that, but by default that's what it's for.
有一个很好的理由可以覆盖它,这与继承有关。假设您想要一个 Base
构造函数来创建基础对象,并使用一个派生
构造函数来创建具有这些特征的派生对象 Base
以及 Derived
的添加/修改。通常(虽然不是我的想法)你看到完成(没有帮助脚本)的方式是:
There's a good reason you can override it, which relates to inheritance. Suppose you want to have a Base
constructor that creates base objects, and a Derived
constructor that creates derived objects with the features of Base
plus the additions/modifications of Derived
. The usual (though not to my mind ideal) way you see that done (absent helper scripts) is:
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
。因此能够解决这个问题非常重要:
The problem is that now, d.constructor === Base
rather than Derived
. So being able to fix that is important:
...
Derived.prototype = new Base(); // So we get all the `Base` stuff
Derived.prototype.constructor = Derived; // Fix up
...
(旁注:所有这些管道&mdash&mdash ;以及围绕超级呼叫的复杂性—为什么这么多人为此创建了帮助脚本,包括(咳嗽) 我的。)
(Side note: All of this plumbing — and complexity around supercalls — is why so many people have created helper scripts for this, including (cough) mine.)
请注意,上述内容并非属于设置继承层次结构的理想方法。这是你经常看到的,但正如我上面所说,并不理想。为了完整起见,这是更好的:
Note that the above is not meant to be an ideal way to set up inheritance hierarchies. It's what you usually see, but as I said above, not ideal. Just for completeness, this is better:
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之前的环境中,你使用垫片/ polyfill Object.create
。但同样,我不直接这样做(并且不推荐它),我使用帮助脚本,因此它是声明性的和可重复的。
...where in a pre-ES5 environment, you use a shim/polyfill for Object.create
. But again, I don't do this directly (and don't recommend it), I use helper scripts so it's declarative and repeatable.
这篇关于anObject.prototype.constructor有什么作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!