instanceof 检查在不设置构造函数的情况下对子类起作用
instanceof check works on subclass without setting constructor
我有以下 JavaScript 代码
function Parent() {
}
function Child() {
}
Child.prototype = Object.create(Parent.prototype);
注意没有声明
Child.prototype.constructor = Child;
我的理解是,由于尚未设置 constructor
属性,instanceof
检查应该会失败 Child
class 的新实例。
var child = new Child();
child instanceof Child; //Should give false
我确认构造函数设置不正确
但是当我 运行 child instanceof Child
它给了我 true
但它应该是 false
,因为构造函数 属性 没有在 Child
的原型上设置为 Child
。
环境
Google Chrome Version 48.0.2564.109 (64-bit)
Ubuntu 14.04 LTS
My understanding is that as the constructor property has not been set the instanceof checks should fail for new instances of Child class.
constructor
属性 根本没有被 instanceof
使用。事实上,直到 ES2015(又名 ES6),constructor
属性 并未用于 JavaScript 本身的 anything。它被定义存在于运行时分配给prototype
属性函数的默认对象上,但未使用 .
让我们看看 instanceof
是如何工作的。考虑:
o instanceof Foo
从 ES2015 开始,instanceof
将检查 Foo
是否实现了一个名为 @@hasInstance
的内部操作,如果是,它将使用该操作来询问 Foo
是否o
是一个实例。
在 ES5 及更早版本中(或者如果 Foo
没有该内部操作),instanceof
将查看 Foo.prototype
指向的对象是否在 [= 上的任何位置25=]的原型链。 (如果“原型链”不是一个熟悉的术语,请查看答案末尾的 * 然后回来。)如果是这样,它 returns true
;如果没有,它 returns 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, and 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
对象指的是”——但这真的很冗长.)
现在,d
对象的原型是 Derived.prototype
。 Derived.prototype
的原型是Base.prototype
。 Base.prototype
的原型是Object.prototype
。 Object.prototype
没有原型(它的 [[Prototype]]
内部插槽是 null
)。
这些对象是d
下的原型链,它们意味着d
是instanceof Object
,instanceof Base
,和 instanceof Derived
.
我有以下 JavaScript 代码
function Parent() {
}
function Child() {
}
Child.prototype = Object.create(Parent.prototype);
注意没有声明
Child.prototype.constructor = Child;
我的理解是,由于尚未设置 constructor
属性,instanceof
检查应该会失败 Child
class 的新实例。
var child = new Child();
child instanceof Child; //Should give false
我确认构造函数设置不正确
但是当我 运行 child instanceof Child
它给了我 true
但它应该是 false
,因为构造函数 属性 没有在 Child
的原型上设置为 Child
。
环境
Google Chrome Version 48.0.2564.109 (64-bit)
Ubuntu 14.04 LTS
My understanding is that as the constructor property has not been set the instanceof checks should fail for new instances of Child class.
constructor
属性 根本没有被 instanceof
使用。事实上,直到 ES2015(又名 ES6),constructor
属性 并未用于 JavaScript 本身的 anything。它被定义存在于运行时分配给prototype
属性函数的默认对象上,但未使用 .
让我们看看 instanceof
是如何工作的。考虑:
o instanceof Foo
从 ES2015 开始,instanceof
将检查 Foo
是否实现了一个名为 @@hasInstance
的内部操作,如果是,它将使用该操作来询问 Foo
是否o
是一个实例。
在 ES5 及更早版本中(或者如果 Foo
没有该内部操作),instanceof
将查看 Foo.prototype
指向的对象是否在 [= 上的任何位置25=]的原型链。 (如果“原型链”不是一个熟悉的术语,请查看答案末尾的 * 然后回来。)如果是这样,它 returns true
;如果没有,它 returns 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, and 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
对象指的是”——但这真的很冗长.)
现在,d
对象的原型是 Derived.prototype
。 Derived.prototype
的原型是Base.prototype
。 Base.prototype
的原型是Object.prototype
。 Object.prototype
没有原型(它的 [[Prototype]]
内部插槽是 null
)。
这些对象是d
下的原型链,它们意味着d
是instanceof Object
,instanceof Base
,和 instanceof Derived
.