Home  >  Article  >  Web Front-end  >  Detailed explanation of the instanceof operator in the ECMAScript7 specification (with examples)

Detailed explanation of the instanceof operator in the ECMAScript7 specification (with examples)

不言
不言Original
2018-09-17 14:01:431597browse

This article brings you a detailed explanation of the instanceof operator (with examples) in the ECMAScript7 specification. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

This article mainly explains the instanceof operator in the ECMAScript7 specification.

Preliminary knowledge

Famous Symbols

"Famous" Symbols refer to built-in symbols, which are defined on the Symbol object. ECMAScript7 uses the form of @@name to reference these built-in symbols. For example, @@hasInstance mentioned below is actually Symbol.hasInstance.

InstanceofOperator(O, C)

O instanceof C will internally call the InstanceofOperator(O, C) abstract operation. The steps of this abstract operation are as follows:

If C The data type is not an object, and a type error exception is thrown;

Let instOfHandler equal GetMethod(C, @@hasInstance), and the approximate semantics is to get the value of the @@hasInstance attribute of object C;

If the value of instOfHandler is not undefined, then:

Returns the result of ToBoolean(? Call(instOfHandler, C, « O »)). The approximate semantics is to execute instOfHandler(O), and then force the call result to Boolean type return.

If C cannot be called, throw an exception of type error;

Return the result of OrdinaryHasInstance(C, O).

OrdinaryHasInstance(C, O)

The steps of OrdinaryHasInstance(C, O) abstract operation are as follows:

If C cannot be called, return false;

If C has an internal slot [[BoundTargetFunction]], then:

Let BC equal the value of C's internal slot [[BoundTargetFunction]];

Return InstanceofOperator(O, BC) The result;

If the type of O is not an object, return false;

Let P equal Get(C, "prototype"), the approximate semantics is to get the value of C.prototype;

If the data type of P is not an object, throw a type error exception;

Repeat the following steps:

Let O equal O.[[GetPrototypeOf]]() As a result, the approximate semantics is to obtain the prototype object of O;

If O is equal to null, return false;

If the result of SameValue(P, O) is true, return true.

SameValue abstract operations refer to ==, === in JavaScript and Object.is() in Object.js(). Object.is() uses the result of this abstract operation.

It can be seen from the above step 2 that if C is a bind function, the InstanceofOperator(O, BC) operation will be re-executed on the target function bound by C.

As can be seen from step 6 above, the prototype object of object O will be repeatedly obtained, and then the prototype object and the prototype attribute of C are compared to see if they are equal, until true is returned when equal, or O becomes null, that is, the traversal is completed. The entire prototype chain returns false.

Function.prototype[@@hasInstance](V)

It can be known from steps 2 and 3 of the above InstanceofOperator(O, C) abstract operation that if C is defined above or inherits @ @hasInstance attribute, the value of the attribute will be called without going to steps 4 and 5. The purpose of steps 4 and 5 is to be compatible with browsers that do not implement the @@hasInstance method. If a function does not define or inherit the @@hasInstance attribute, then the default instanceof semantics will be used, which is the steps described by the OrdinaryHasInstance(C, O) abstract operation.

In the ECMAScript7 specification, the @@hasInstance attribute is defined on the prototype attribute of Function. The steps of Function.prototype[@@hasInstance](V) are as follows:

Let F equal this value;

Return the result of OrdinaryHasInstance(F, V).

So, you can see that by default, the semantics of instanceof are the same, and they all return the result of OrdinaryHasInstance(F, V). Why does it say by default? Because you can override the Function.prototype[@@hasInstance] method to customize the behavior of instanceof.

Example

function A () {}
function B () {}

var a = new A
a.__proto__ === A.prototype // true
a.__proto__.__proto__ === Object.prototype // true
a.__proto__.__proto__.__proto__ === null // true

a instanceof A // true
a instanceof B // false

It can be seen from step 6 of OrdinaryHasInstance(C, O):

For an instanceof A, P is A.prototype, in the first cycle At this time, the prototype object a._proto__ of a is A.prototype, that is, O in the step is A.prototype, so true is returned;

For a instanceof B, P is B.prototype, in the During the first loop, the prototype object a._proto__ of a is A.prototype, not equal to P; execute the second loop, at this time O is a.__proto__.__proto__, which is Object.prototype, not equal to P; execute The third loop, at this time O is a.__proto__.__proto__.__proto__, which is null, that is, the prototype chain has been traversed, so false is returned.

Follow the above example:

A.prototype.__proto__ = B.prototype

a.__proto__ === A.prototype // true
a.__proto__.__proto__ === B.prototype // true
a.__proto__.__proto__.__proto__ === Object.prototype // true
a.__proto__.__proto__.__proto__.__proto__ === null // true

a instanceof B // true

In the above example, we set B.prototype to be a link in the prototype chain of a, so that a instanceof B is in OrdinaryHasInstance(C, In the second loop of step 6 of O), true was returned.

From the second step of OrdinaryHasInstance(C, O), we know that the behavior of the bind function is different from the behavior of the ordinary function:

function A () {}
var B = A.bind()

B.prototype === undefined // true

var b = new B
b instanceof B // true
b instanceof A // true

As can be seen from the above example, B.prototype is undefined. Therefore, the return result of instanceof acting on the bind function is actually the return value acting on the bound target function, which basically has nothing to do with the bind function.

As can be seen from steps 2 and 3 of InstanceofOperator(O, C), we can customize the behavior of instanceof by overriding the @@hasInstance method on the prototype:

function A () {}
var a = new A
a instanceof A // true

A[Symbol.hasInstance] = function () { return false }
a instanceof A // ?

在chrome浏览器测试了一下,发现还是输出true。然后看了一下ECMAScript6的文档,
ECMAScript6文档里面还没有规定可以通过@@hasInstance改变instanceof的行为,所以应该是目前chrome浏览器还没有实现ECMAScript7中的instanceof操作符的行为。

总结

本文主要讲解ECMAScript7规范中的instanceof操作符,希望大家能有所收获。

The above is the detailed content of Detailed explanation of the instanceof operator in the ECMAScript7 specification (with examples). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn