javascript instanceof 内部机制探析


Posted in Javascript onOctober 15, 2010

比如:

// 代码 1 
function Pig() {} 
var pig = new Pig(); 
alert(pig instanceof Pig); // => true function FlyPig() {} 
FlyPig.prototype = new Pig(); 
var flyPig = new FlyPig(); 
alert(flyPig instanceof Pig); // => true

来看另一段代码:
// 代码 2 
function Pig() { Pig.prototype = {/* some code */} } 
var pig = new Pig(); 
alert(pig instanceof Pig); // => false

为何上面的猪 pig 不再是猪 Pig 了呢?
当一个对象是某个类的实例时,意味着这个对象具有该类的方法和属性。在 JavaScript 中,一个猪类的特性体现在原型中:
// 代码 3 
function Pig() {} 
Pig.prototype = { 
"吃猪食": function() {}, 
"睡觉": function() {}, 
"长膘": function() {} 
}; 
var pig = new Pig(); 
alert(pig instanceof Pig); //=> true

如果动态改变了猪的特性,让猪变成了牛:
// 代码 4 
Pig.prototype = { 
"吃草": function() {}, 
"犁田": function() {} 
}; 
var niu= new Pig(); 
alert(pig instanceof Pig); //=> false 
alert(niu instanceof Pig); //=> true

当未改变 Pig 的 prototype 时,猪还是猪,因此代码 3 中 pig 是 Pig 的实例。当改变 prototype 后,猪已经不是猪,而是披着猪皮的牛了。因此代码 4 中 pig 不再是 Pig 的实例,niu 反而是 Pig 的实例。

进一步分析前,先回顾一下 new 的内部机制。代码 2 中的 new Pig() 实际上等价为:

// var pig = new Pig() 的等价伪代码: 
var pig = (function() { 
var o = {}; 
o.__proto__ = Pig.prototype; // line 2 
Pig.call(o); 
Pig.prototype = {/* some code */}; // line 4 
return o; // line 5 
})();

可以看出,在 line 2 时,o.__proto__ 指向了 Pig.prototype 指向的值。但在 line 4 时,Pig.prototype 指向了新值。也就是说,在 line 5 返回时,pig.__proto__ !== Pig.prototype. 正是这个变化,导致了代码 2 中的 pig 不是 Pig.

已经可以大胆推论出:instanceof 判断 pig 是不是 Pig 的依据是:看隐藏的 pig.__proto__ 属性是否等于 Pig.prototype !

为了进一步确认,我们可以在 Firefox 下模拟 instanceof 的内部实现代码:

/** 
* Gecko 引擎下,模拟 instanceof 
*/ 
function _instanceof(obj, cls) { 
// instanceof 的左操作数必须是非null对象或函数对象 
if((typeof obj !== "object" || obj === null) 
&& typeof obj !== "function") { 
return false; 
} // instanceof 的右操作数必须是函数对象 
if(typeof cls !== "function") { 
throw new Error("invalid instanceof operand (" + cls + ")"); 
} 
// 向上回溯判断 
var p = obj.__proto__, cp = cls.prototype; 
while(p) { 
if(p === cp) return true; 
p = p.__proto__; 
} 
return false; 
}

测试页面:simulate-intanceof.html

最后考考大家:

function Bird() {} 
var bird = new Bird(); 
var o = {}; 
bird.__proto__ = o; 
Bird.prototype = o; 
alert(bird instanceof Bird); // true or false?
Javascript 相关文章推荐
Extjs学习笔记之二 初识Extjs之Form
Jan 07 Javascript
从jQuery.camelCase()学习string.replace() 函数学习
Sep 13 Javascript
jquery获取URL中参数解决中文乱码问题的两种方法
Dec 18 Javascript
瀑布流布局代码一例
Apr 11 Javascript
取得元素的左和上偏移量的方法
Sep 17 Javascript
js使用Array.prototype.sort()对数组对象排序的方法
Jan 28 Javascript
JS实现固定在右下角可展开收缩DIV层的方法
Feb 13 Javascript
JS实现表格数据各种搜索功能的方法
Mar 03 Javascript
jquery制做精致的倒计时特效
Jun 13 Javascript
JS添加删除DIV的简单实例
Jul 08 Javascript
微信小程序 wx.request(object) API详解及实例代码
Sep 30 Javascript
Vue入门之数据绑定(小结)
Jan 08 Javascript
理解Javascript_07_理解instanceof实现原理
Oct 15 #Javascript
JavaScript 对象模型 执行模型
Oct 15 #Javascript
理解Javascript_06_理解对象的创建过程
Oct 15 #Javascript
JavaScript聚焦于第一个字段的代码
Oct 15 #Javascript
JavaScript访问样式表代码
Oct 15 #Javascript
IE下js调试工具Companion.JS
Oct 15 #Javascript
jquery $.ajax各个事件执行顺序
Oct 15 #Javascript
You might like
短波收音机简介
2021/03/01 无线电
discuz加密解密函数使用方法和中文注释
2014/01/21 PHP
thinkPHP使用pclzip打包备份mysql数据库的方法
2016/04/30 PHP
Yii控制器中操作视图js的方法
2016/07/04 PHP
PHP中trait使用方法详细介绍
2017/05/21 PHP
thinkphp 框架数据库切换实现方法分析
2020/05/18 PHP
jquery 之 $().hover(func1, funct2)使用方法
2012/06/14 Javascript
jquery中animate的stop()方法作用实例分析
2015/01/30 Javascript
IScroll5 中文API参数说明和调用方法
2016/05/21 Javascript
JS实现兼容火狐及IE iframe onload属性的遮罩层隐藏及显示效果
2016/08/23 Javascript
Vue.js使用v-show和v-if的注意事项
2016/12/13 Javascript
利用Node.js编写跨平台的spawn语句详解
2017/02/12 Javascript
jQuery树控件zTree使用方法详解(一)
2017/02/28 Javascript
Node.js log4js日志管理详解
2018/07/31 Javascript
node.js 使用 net 模块模拟 websocket 握手进行数据传递操作示例
2020/02/11 Javascript
[02:43]DOTA2英雄基础教程 德鲁伊
2014/01/13 DOTA
对python Tkinter Text的用法详解
2018/10/11 Python
如何利用Python分析出微信朋友男女统计图
2019/01/25 Python
利用ImageAI库只需几行python代码实现目标检测
2019/08/09 Python
Pycharm debug调试时带参数过程解析
2020/02/03 Python
利用Python脚本批量生成SQL语句
2020/03/04 Python
django之从html页面表单获取输入的数据实例
2020/03/16 Python
Selenium 配置启动项参数的方法
2020/12/04 Python
Bench加拿大官方网站:英国城市服装品牌
2017/11/03 全球购物
乐高西班牙官方商店:LEGO Shop ES
2019/12/01 全球购物
乔迁宴答谢词
2014/01/21 职场文书
病媒生物防治方案
2014/05/13 职场文书
2014院党委领导班子及其成员群众路线对照检查材料思想汇报
2014/10/04 职场文书
房屋买卖协议样本
2014/11/16 职场文书
幼儿园大班毕业评语
2014/12/31 职场文书
财务部岗位职责范本
2015/04/14 职场文书
交通事故起诉书
2015/05/19 职场文书
大学生学习十八届五中全会精神心得体会
2016/01/05 职场文书
员工工作心得体会
2019/05/07 职场文书
导游词之云南丽江古城
2019/09/17 职场文书
阿里云ECS云服务器快照的概念以及如何使用
2022/04/21 Servers