为什么在JavaScript中,“Object instanceof Function”和“Function instanceof Object”返回true? [英] Why in JavaScript both "Object instanceof Function" and "Function instanceof Object" return true?
问题描述
为什么在JavaScript中同时执行 Object instanceof Function
和函数instanceof Object return
true
?
我在Safari WebInspector中试了一下。
我花了一段时间才弄清楚,但它真的值得花时间。首先,让我们看看 instanceof
是如何工作的。
从MDN ,
instanceof
运算符测试对象是否在其原型链中包含原型
>
。
现在,让我们看看
instanceof
由ECMA 5.1规范定义,
$ b
生产
RelationalExpression: RelationalExpression instanceof ShiftExpression
的计算方法如下:
- 让
lref
是评估RelationalExpression
的结果。
- 让
lval
code> GetVa lue(lref)
让 rref
成为评估ShiftExpression的结果
。
让 rval
为GetValue(rref)$ c $如果
Type(rval)
不是Object,则抛出TypeError $ c $如果
rval
没有[[HasInstance]] $ c $> c>内部方法,抛出
TypeError
异常。
返回调用 [[HasInstance] ] 内部方法
rval
带参数lval
。
首先评估左右手表达式( GetValue
)和那么右边的结果应该是一个带 [[HasInstance]]
内部方法的对象。不是所有的对象都有 [[HasInstance]]
内部方法,但是函数。例如,以下将失败
console.log(Object instanceof {});
#TypeError:期望在instanceof check中有一个函数,但得到#< Object>
[[HasInstance]]
现在,让我们看看 [[HasInstance ]]
已在ECMA 5.1规范中定义
假设
F
是一个Function对象。
当
[[HasInstance]]
internal方法F
用值V
调用,则采取以下步骤:
- 如果
V
不是对象,则返回false
。
- 让
O
成为调用[[Get]]
内部结果方法F
,属性名称prototype
。
- c $ c> Type(O)不是Object,抛出
TypeError
异常。
- 重复
- 让
V
为[[Prototype]]
V
的内部属性。
- 如果
V
为null
,返回false
。
- 如果
O
和V
引用同一个对象,则返回true <
它非常简单。取原型
属性 F
,并将其与 [[Prototype]]
O
的内部属性,直到它变成 null
或 prototype
F
与 O
相同。
[[prototype]]
内部属性
首先让我们看看什么是 [[prototype]]
内部属性,
所有对象都有一个名为
[[Prototype]]
的内部属性。该属性的值是null
或一个对象,用于实现继承。本地对象是否可以将主对象作为其[[Prototype]]
取决于实现。每个[[Prototype]]
链必须具有有限长度(也就是说,从任何对象开始,递归地访问[[Prototype]]
内部属性必须最终导致null
值)。
注意:我们可以使用 Object.getPrototypeOf
功能。
原型
属性
[[HasInstance]]
也会谈到另一个名为 prototype
,这是特定于 Function
对象的。
原型
属性的值用于初始化[[Prototype ]]
调用Function对象作为新创建对象的构造函数之前新创建对象的内部属性。
这意味着,当一个函数对象被用作构造函数时,将会创建一个新对象并且新对象将拥有它内部 [[Prototype]]
用这个 prototype
属性初始化。例如,
函数Test(){}
Test.prototype.print = console.log;
console.log(Object.getPrototypeOf(new Test())=== Test.prototype);
#true
实际问题
<现在让我们回到实际的问题。让我们来看第一个案例:
console.log(Object instanceof Function);
#true
它将读取 Function.prototype $首先c $ c>,它会尝试查找该对象是否位于
Object
的原型层次结构中。让我们看看结果如何
console.log(Function.prototype);
#[功能:空]
console.log(Object.getPrototypeOf(Object));
#[功能:空]
console.log(Object.getPrototypeOf(Object)=== Function.prototype);
$ true
由于 Function.prototype
匹配 Object
的内部属性 [[Prototype]]
,它返回真正
。
现在让我们来看第二种情况
console.log(Function instanceof Object);
#true
console.log(Object.prototype);
#{}
console.log(Object.getPrototypeOf(Function));
#[功能:空]
console.log(Object.getPrototypeOf(Function)=== Object.prototype);
#false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
#{}
Object.getPrototypeOf(Object.getPrototypeOf(Function))=== Object.prototype
#true
在这里,首先我们得到 Object.prototype
,它是 {}
。现在它试图找出在 Function
的原型链中是否存在相同的对象 {}
。 函数
的直接父项是和空函数。
console.log Object.getPrototypeOf(功能));
#[功能:空]
它与 Object.prototype
console.log(Object.getPrototypeOf(Function)=== Object。原型);
#false
但 [[HasInstance]]
算法并不止于此。它重复并且获得了更多的级别。
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
#{}
这与 Object相同。原型
。这就是为什么这会返回 true
。
Why in JavaScript do both Object instanceof Function
and Function instanceof Object
return true
?
I tried it in Safari WebInspector.
It took a while for me to figure out but its really worth the time spent. First, let us see how instanceof
works.
Quoting from MDN,
The
instanceof
operator tests whether an object has in its prototype chain theprototype
property of a constructor.
[instanceof]
Now, let us see how instanceof
is defined by ECMA 5.1 Specification,
The production
RelationalExpression: RelationalExpression instanceof ShiftExpression
is evaluated as follows:
- Let
lref
be the result of evaluatingRelationalExpression
.- Let
lval
beGetValue(lref)
.- Let
rref
be the result of evaluatingShiftExpression
.- Let
rval
beGetValue(rref)
.- If
Type(rval)
is not Object, throw aTypeError
exception.- If
rval
does not have a[[HasInstance]]
internal method, throw aTypeError
exception.- Return the result of calling the
[[HasInstance]]
internal method ofrval
with argumentlval
.
First the left and right hand side expressions are evaluated (GetValue
) and then right hand side result should be an Object with [[HasInstance]]
internal method. Not all objects will have [[HasInstance]]
internal method, but functions. For example, the following will fail
console.log(Object instanceof {});
# TypeError: Expecting a function in instanceof check, but got #<Object>
[[HasInstance]]
Now, let us see how [[HasInstance]]
has been defined in the ECMA 5.1 specification,
Assume
F
is a Function object.When the
[[HasInstance]]
internal method ofF
is called with valueV
, the following steps are taken:
- If
V
is not an object, returnfalse
.- Let
O
be the result of calling the[[Get]]
internal method ofF
with property name"prototype"
.- If
Type(O)
is not Object, throw aTypeError
exception.- Repeat
- Let
V
be the value of the[[Prototype]]
internal property ofV
.- If
V
isnull
, returnfalse
.- If
O
andV
refer to the same object, returntrue
.
It is so simple. Take the prototype
property of F
and compare it with the [[Prototype]]
internal property of O
until it becomes null
or prototype
of F
is the same as O
.
[[prototype]]
internal property
First let us see what is the [[prototype]]
internal property,
All objects have an internal property called
[[Prototype]]
. The value of this property is eithernull
or an object and is used for implementing inheritance. Whether or not a native object can have a host object as its[[Prototype]]
depends on the implementation. Every[[Prototype]]
chain must have finite length (that is, starting from any object, recursively accessing the[[Prototype]]
internal property must eventually lead to anull
value).
Note: We can get this internal property with the Object.getPrototypeOf
function.
prototype
property
[[HasInstance]]
also talks about another property called prototype
, which is specific to the Function
objects.
The value of the
prototype
property is used to initialise the[[Prototype]]
internal property of a newly created object before the Function object is invoked as a constructor for that newly created object.
This means that, when a function object is used as a constructor, a new object will be created and the new object will have its internal [[Prototype]]
initialized with this prototype
property. For example,
function Test() {}
Test.prototype.print = console.log;
console.log(Object.getPrototypeOf(new Test()) === Test.prototype);
# true
Actual problem
Now let us get back to the actual question. Lets take the first case
console.log(Object instanceof Function);
# true
It will fetch Function.prototype
first and it will try and find if that object is in the prototype hierarchy of Object
. Let us see how that turns out
console.log(Function.prototype);
# [Function: Empty]
console.log(Object.getPrototypeOf(Object));
# [Function: Empty]
console.log(Object.getPrototypeOf(Object) === Function.prototype);
# true
Since the Function.prototype
matches the Object
's internal property [[Prototype]]
, it returns true
.
Now lets take the second case
console.log(Function instanceof Object);
# true
console.log(Object.prototype);
# {}
console.log(Object.getPrototypeOf(Function));
# [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
# false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
# {}
Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype
# true
Here, first we get the Object.prototype
, which is {}
. Now it is trying to find if the same object {}
is there in the Function
's prototype chain. Immediate parent of Function
is and Empty function.
console.log(Object.getPrototypeOf(Function));
# [Function: Empty]
It is not the same as Object.prototype
console.log(Object.getPrototypeOf(Function) === Object.prototype);
# false
But the [[HasInstance]]
algorithm doesn't stop there. It repeats and gets up one more level
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
# {}
And this is the same as Object.prototype
. That is why this returns true
.
这篇关于为什么在JavaScript中,“Object instanceof Function”和“Function instanceof Object”返回true?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!