我的理解是,由于尚未设置构造函数属性,因此对 Child 类的新实例的 instanceof 检查应该失败。
instanceof 根本不使用 constructor 属性。事实上,直到 ES2015(又名 ES6),constructor 属性并没有用于 JavaScript 本身的 anything。它定义存在于运行时分配给函数的prototype属性的默认对象上,但未使用。
让我们看看instanceof 是如何工作的。考虑:
o instanceof Foo
从 ES2015 开始,instanceof 将检查 Foo 是否实现了一个名为 @@hasInstance 的内部操作,如果是,它将使用该操作询问 Foo o 是否是一个实例。
在 ES5 和更早版本中(或者如果 Foo 没有该内部操作),instanceof 将查看 Foo.prototype 指向的对象是否位于 o 原型链上的任何位置。 (如果“原型链”不是一个熟悉的术语,请看答案末尾的*,然后再回来。)如果是,则返回true;如果不是,则返回false。
例如,这是instanceof 的概念实现,省略了一些细节:
function isAnInstance(obj, func) {
// Start: ES2015+ part
const hasInstance = func[Symbol.hasInstance];
if (hasInstance) {
return hasInstance.call(func, obj);
}
// End: ES2015+ part
// Start: The OrdinaryHasInstance specification operation
for (let p = Object.getPrototypeOf(obj); p; p = Object.getPrototypeOf(p)) {
if (p === func.prototype) {
return true;
}
}
return false;
// End: The OrdinaryHasInstance specification operation
}
JavaScript 内置的函数do 有@@hasInstance(它们从Funtion 继承它),但它所做的只是上面显示的 OrdinaryHasInstance 操作。请参阅规范here、here 和here。
我们可以从您的问题中看到constructor 没有涉及,从这个简单的演示中也可以看出:
var p = {};
var o = Object.create(p);
var Foo = function() {};
Foo.prototype = p;
console.log(o instanceof Foo); // true
console.log(o.hasOwnProperty("constructor")); // false
console.log(
Object.getPrototypeOf(o).constructor === Object
); // true
注意:
-
o 不是通过 Foo 创建的。
- 事实上,
Foo 甚至在o 创建之后才存在。
-
o 没有自己的 constructor 属性。
-
o 原型的constructor 属性是Object,而不是Foo。
...然而instanceof 说“是的,看起来它是一个 Foo。” :-) 纯粹是因为Foo.prototype 指向的对象也在o 的原型链上。
* “原型链”
您清楚地知道 JavaScript 中的对象具有原型,它们可以从原型中继承属性。这些原型是对象,所以它们有原型。所以你会得到一个原型“链”。
考虑一个两级(可以说是三级)继承层次结构,这里在 ES5 中:
function Base() {
}
function Derived() {
Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;
...或在 ES2015 中:
class Base {
}
class Derived extends Base {
}
现在我们使用它:
var d = new Derived();
(你在下面看到“d 对象”和类似的东西,当然我的意思是“d 所指的对象”——但这真的很冗长。) p>
现在,d 对象的原型是 Derived.prototype。 Derived.prototype 的原型是 Base.prototype。 Base.prototype 的原型是 Object.prototype。 Object.prototype 没有原型(其[[Prototype]] 内部插槽为null)。
这些对象是d 底层的原型链,它们意味着d 是instanceof Object、instanceof Base 和instanceof Derived。