JS的 instanceof 方法
http://www.cnblogs.com/jasonxuli/p/6769282.html
这是 2014-12-10 发在 iteye 上的文章
今天突然想起js的原型继承模型和相关的prototype,constructor,觉得有点模糊,就写了个例子:
var log = console.log;
function A(){
this.value = 1;
}
var a = new A();
log('a.value = ', a.value); // a.value = 1
log('a instanceof A: ', a instanceof A); // a instanceof A: true
function B(){
this.value = 2;
}
var b = new B();
A.prototype = b;
var aa = new A();
log(aa.constructor == b.constructor); // true
log('a.value = ', a.value); // a.value = 1
log('b.value = ', b.value); // b.value = 2
log('aa.value = ', aa.value); // aa.value = 1
log('a instanceof A: ', a instanceof A); // a instanceof A: false
log('a instanceof B: ', a instanceof B); // a instanceof B: false
其他的都没问题,最后两行突然有点让我恍惚:
为什么在A继承了B之后,a就不是A的实例了呢?
于是就去查instanceof的文档,ECMA 262 5.1版:
11.8.6The instanceof operator
The production RelationalExpression : RelationalExpression instanceof ShiftExpression is evaluated as follows:
- Let lref be the result of evaluating RelationalExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating ShiftExpression.
- Let rval be GetValue(rref).
- If Type(rval) is not Object, throw a TypeError exception.
- If rval does not have a [[HasInstance]] internal method, throw a TypeError exception.
- Return the result of calling the [[HasInstance]] internal method of rval with argument lval.
2, 4 条提到的GetValue又是一个坑,暂且不管,去看6, 7提到的内部方法[[HasInstance]]:
15.3.5.3[[HasInstance]] (V)
Assume F is a Function object.
When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:
- If V is not an object, return false.
- Let O be the result of calling the [[Get]] internal method of F with property name
"prototype". - If Type(O) is not Object, throw a TypeError exception.
- Repeat
- Let V be the value of the [[Prototype]] internal property of V.
- If V is
null, return false. - If O and V refer to the same object, return true.
这一条大概等同于下面的逻辑:
F为instanceof表达式的右值,也就是constructor;V是左值,也就是instance;
HasInstance(V){
if(typeof(V) != 'object')
return false;
var O = F.get('prototype'); // get 为内部方法
if(typeof(O) != Object)
throw new TypeError();
while(1){ // 循环实例V的原型链
V = V.__proto__; // 获取实例V的内部属性prototype,可以用Object.getPrototypeOf(V)获取
if(V == null) // Object.prototype.__proto__ 为null,这也是最终的跳出语句
return false;
if(O === V)
return true;
}
}
F.HasInstance(V);
查了文档,算是搞明白了:
比较时使用的是实例的内部属性__proto__和构造函数的prototype,而实例内部属性__proto__只在被初始化的时候被设置为构造函数的prototype,因此
A.prototype = b; // A 继承了 B
而a的内部的__proto__还是A{},也就是a记得自己的亲爹是A{},但是现在的A认B做父了,所以a不承认是A的直系了。
a instanceof A; // false
a instanceof B; // false
有点儿刻舟求剑的感觉不?!
JS的 instanceof 方法的更多相关文章
- js判断类型方法
在JavaScript中,有5种基本数据类型和1种复杂数据类型,基本数据类型有:Undefined, Null,Boolean, Number和String:复杂数据类型是Object,Object中 ...
- 各种实现js继承的方法总结
昨天主要介绍了原型,在js中,原型,原型链和继承是三个很重要的概念,而这几个概念也是面试中经常会被问到的问题,今天,就把昨天还没总结的原型链和继承继续做一个整理,希望大家一起学习,一起进步呀O(∩_∩ ...
- 原生JS实现new方法、new一个对象发生的四部、new里面常用的优先级
一.js中new一个对象的过程 首先了解new做了什么,使用new关键字调用函数(new ClassA(…))的具体步骤: 1.创建一个新对象: var obj = {}; 2.设置新对象的const ...
- TODO:Node.js pm2使用方法
TODO:Node.js pm2使用方法 pm2 是一个带有负载均衡功能的Node应用的进程管理器. 当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完 ...
- 【转载】JS中bind方法与函数柯里化
原生bind方法 不同于jQuery中的bind方法只是简单的绑定事件函数,原生js中bind()方法略复杂,该方法上在ES5中被引入,大概就是IE9+等现代浏览器都支持了(有关ES5各项特性的支持情 ...
- 前端Js跨域方法汇总—剪不断,理还乱,是跨域
1.通过jsonp跨域2.通过修改document.domain来跨子域(iframe)3.隐藏的iframe+window.name跨域4.iframe+跨文档消息传递(XDM)5.跨域资源共享 C ...
- 原生JS事件绑定方法以及jQuery绑定事件方法bind、live、on、delegate的区别
一.原生JS事件绑定方法: 1.通过HTML属性进行事件处理函数的绑定如: <a href="#" onclick="f()"> 2.通过JavaS ...
- JS调用OC方法并传值,OC调用JS方法并传值////////////////////////zz
iOS开发-基于原生JS与OC方法互相调用并传值(附HTML代码) 最近项目里面有有个商品活动界面,要与web端传值,将用户在网页点击的商品id 传给客户端,也就是js交互,其实再说明白一点 ...
- 原生JS中apply()方法的一个值得注意的用法
今天在学习vue.js的render时,遇到需要重复构造多个同类型对象的问题,在这里发现原生JS中apply()方法的一个特殊的用法: var ary = Array.apply(null, { &q ...
随机推荐
- poj_2739 尺取法
题目大意 给定一个数字N,N可能由1个或多个连续的素数求和得到,比如41 = 2+3+5+7+11+13, 41 = 11+13+17, 41 = 41.求出对于N,所有可能的组合形式. 题目分析 先 ...
- 【转】实现Ribbon风格的窗体
随着office2007的兴起,微软让我们看到了Ribbon风格的窗体,现在很多软件也都开始使用Ribbon风格.那么我们如果要自己开发,应当怎么做呢?本文就是为大家解开这个疑团的. 首先,Delph ...
- Android Runtime.getRuntime().exec
try { // Executes the command. Process process = Runtime.getRuntime().exec(cmd); // NOTE: You can wr ...
- Web和Native使用外部字体ttf方法
论坛教程:http://bbs.egret.com/forum.php?mod=viewthread&tid=24879&extra=&highlight=%E5%AD%97% ...
- Linux下安装和卸载jdk步骤详述
安装jdk 1.下载jdk8 jdk下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-21331 ...
- couldn't connect to host
“couldn't connect to host” 这样的错误可能是主机不可到达,或者端口不可到达. ping OK只代表主机可以到达. 端口不可到达可能是由于HTTP 服务器未启动或者监听在其他端 ...
- poj3764 The XOR Longest Path【dfs】【Trie树】
The xor-longest Path Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10038 Accepted: ...
- 用Oracle实现ASH的数据透视图
11g里面有个很有用的新特性,对数据透视图的支持. 简单而言,它可以实现宽表和窄表之间的转化.举一个例子,有一张表记录了全校所有班级所有学生的成绩(A,B,C,D,E),现在想统计每个班级里每个分数级 ...
- 缓存策略 半自动化就是mybaitis只支持数据库查出的数据映射到pojo类上,而实体到数据库的映射需要自己编写sql语句实现,相较于hibernate这种完全自动化的框架我更喜欢mybatis
springboot入门(三)-- springboot集成mybatis及mybatis generator工具使用 - FoolFox - CSDN博客 https://blog.csdn.net ...
- BBS - 预备知识
一.中介模型 四个项目: 苑昊 博客(BBS) (7-8) CRM 1.权限组件 (3) 2.start组件 -- admin (5) 1.使用 2.源码 django 源码 (面向对象) 以源码为导 ...