instanceof是如何在JavaScript中实现的
How instanceof is implemented in JavaScript
让我们考虑以下代码片段:
function A() {}
var obj = new A();
function B() {};
obj.constructor = B;
console.info("1: ", obj.constructor); //Function B
console.info("2: ", obj instanceof A); //true
console.info("3: ", obj instanceof B); //false
我想,要决定该对象是否是某个函数类的实例,JS引擎必须检查该对象是否具有相同的构造函数属性。但这似乎并没有发生,因为即使重写对象的构造函数属性也不会改变它的输出实例。
ECMAScript 262规范将告诉您这一点。直接从其引用`instanceof operator部分:
11.8.6运算符的实例
ShiftExpression的生产RelativalExpression:RelativalExpression实例的求值如下:
- 设lref是计算RelationalExpression的结果
- 设lval为GetValue(lref)
- 设rref是计算ShiftExpression的结果
- 设rval为GetValue(rref)
- 如果Type(rval)不是Object,则引发TypeError异常
- 如果rval没有[[HasInstance]]内部方法,则引发TypeError异常
- 返回使用参数lval调用rval的[[HasInstance]]内部方法的结果
至于[[HasInstance]]
是什么,规范还在对象内部属性和方法部分中定义为:
[[HasInstance]]
返回一个布尔值,指示参数是否可能是由该对象构造的Object。在标准的内置ECMAScript对象中,只有Function对象实现[[HasInstance]]
对此的进一步解读:http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.5.3
此链接声明:
instanceof运算符测试中constructor.prototype的存在对象的原型链。
简短版本
obj instanceof A
查看A.prototype
引用的对象是否在obj
的原型链中的任何位置。它根本不使用constructor
。
更多详细信息
这在规范中由§11.8.5-运算符的实例涵盖,该实例(通过§8.6.2间接地)表示,它调用函数对象的[[HasInstance]]
内部方法,传入我们正在测试的对象。Function
的[[HasInstance]]
(在§15.3.5.3中)表示,它从函数的prototype
属性中获取对象引用,然后如果该对象位于目标对象原型链中的任何位置,则返回true
,如果不在,则返回false
。
它不使用constructor
(事实上,JavaScript本身没有任何功能)—如果你仔细想想,它不能,因为一个对象的constructor
属性只能指向一个函数,但一个对象可以是instanceof
多个函数—例如,在伪经典继承的情况下:
function A() {}
function B() {
A.call(this);
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
var obj = new B();
snippet.log(obj instanceof A); // true
snippet.log(obj instanceof B); // true
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
两者都是真的,因为A.prototype
和B.prototype
引用的两个对象都在obj
的原型链中。
instanceof
为真并不一定意味着obj
是由对A
的调用直接或间接创建的;它只是表明它们之间有一个模糊的链接(A.prototype
指的是一个也在obj
的原型链中的对象)。它通常意味着A
参与了创建对象,但不能保证。
例如:
function A() {}
var obj = Object.create(A.prototype);
snippet.log(obj instanceof A); // true
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
请注意,根本没有调用A
来创建对象。
或者可能更清晰和/或更引人注目:
function A() {}
var p = {};
var obj = Object.create(p);
snippet.log(obj instanceof A); // false
A.prototype = p;
snippet.log(obj instanceof A); // true
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
还有一个不寻常但完全可能的版本:
function A() {}
function B() {}
A.prototype = B.prototype = {};
var obj = new A();
snippet.log(obj instanceof B); // true
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
或者这个:
function A() {}
function B() {}
var obj = new B();
snippet.log(obj instanceof A); // false
A.prototype = B.prototype;
snippet.log(obj instanceof A); // true
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
- 绑定函数时在IE7中未实现Javascript错误
- 可以't实现JavaScript翻转计数器
- 如何实现 Javascript 自动完成功能
- 实现JavaScript内部方法的源代码
- 当实现javascript倒计时时,其他html元素将消失
- 在aspx页面中实现javascript时出现问题
- 这是实现javascript字符串长度属性的正确方法吗
- 将递归函数转换为异步 CPS 实现 (javascript)
- 如何在Wordpress中实现javascript
- 在jQuery方法中实现Javascript变量
- 无法实现 JavaScript 代码
- 在 Rails 应用程序中实现 JavaScript 库
- 如何实现 JavaScript 对象继承
- 我将如何实现JavaScript
- 当浏览器开始实现JavaScript时,如何在支持一两个版本较旧的浏览器的同时开始使用它们
- 有没有其他方法可以在纯python中实现javascript的onClick()函数
- 如何在JavaCC中实现JavaScript自动分号插入
- 响应式网页设计 - 如何实现JavaScript部分
- 用Selfish实现Javascript中的简单继承
- 如何实现JavaScript/ECMAScript“;这里没有线路终止器”;JavaCC中的规则