为什么 javascript 函数原型需要修复构造函数?

Why javascript Function prototype need to fix constuctor?

例如。当他们将对象分配给函数的原型时,我通常会看到 JQuery 源代码或其他 javascript 框架源代码,他们通常这样做:

function A(){}
A.prototype = {
    constructor: A,
    // ....
}

我真的很困惑。我的意思是为什么必须这样做?

在JavaScript中,所有正常创建的函数都有一个prototype 属性,它最初是由JavaScript引擎创建的一个对象,其中有一个属性: constructor,指回函数。所以对于

function A() {
}

...我们知道,最初,A.prototype.constructor === A。这也意味着通过 new A 创建的对象将继承 constructor,因此:

var o = new A();
console.log(o.constructor === A); // true

但是,如果您 prototype 属性 上的对象 prototype 替换为其他对象,就像您的代码片段所做的那样,那么新对象 constructor 属性(它继承的)指向错误的函数,除非你修复它:

function A() {
}
A.prototype = {}; // Replace the object
var o = new A();
console.log(o.constructor === A);      // false
console.log(o.constructor === Object); // true

糟糕。这就是为什么你引用的片段在它分配给 A.prototype.

的对象上设置 constructor

但是 constructor 属性 有什么意义呢?实际上,JavaScript 规范中没有任何内容 使用 属性;唯一提到的与上述有关,确保 prototype 属性 上的初始对象有 constructor 引用函数。

但是一些代码(包括一些库)可能假设 constructor 被设置为 "properly"(例如,JavaScript 引擎默认的方式),并且可能会尝试使用它来确定一个对象 "is" 是什么(尽管通常很少有理由这样做;在极少数情况下,当您真正关心时,instanceof 通常是更好的检查方法,因为它允许派生对象)。或者他们可能会尝试在克隆操作中使用它,尽管从 ES5 开始有更好的方法。

在任何情况下,因为那里有(罕见的)代码可能依赖于 constructor 属性 被 JavaScript 引擎设置,所以表现良好替换 prototype 属性 的代码完全设置 constructor 与 JavaScript 引擎相同的方式,以防万一。

实际上,很常见 人们在替换 prototype 属性 上的对象时省略该步骤,因此依赖 constructor 在新代码中不是最佳实践。但确保您正确设置 constructor 可能仍然是,以防万一。