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 相关文章推荐
js post方式传递提交的实现代码
May 31 Javascript
JS俄罗斯方块,包含完整的设计理念
Dec 11 Javascript
JQuery显示隐藏DIV的方法及代码实例
Apr 16 Javascript
jQuery通过Ajax返回JSON数据
Apr 28 Javascript
jQuery实现模仿微博下拉滚动条加载数据效果
Dec 25 Javascript
基于JavaScript代码实现微信扫一扫下载APP
Dec 30 Javascript
JS获取当前脚本文件的绝对路径
Mar 02 Javascript
javascript 数组的正态分布排序的问题
Jul 31 Javascript
深入理解Angular2 模板语法
Aug 07 Javascript
JS实现页面打印(整体、局部)
Aug 18 Javascript
详解vue 组件之间使用eventbus传值
Oct 25 Javascript
vue数据控制视图源码解析
Mar 28 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
php 数组的一个悲剧?
2011/05/11 PHP
php无限遍历目录示例
2014/02/21 PHP
基于php编程规范(详解)
2017/08/17 PHP
为数据添加append,remove功能
2006/10/03 Javascript
Javascript Throttle & Debounce应用介绍
2013/03/19 Javascript
热点新闻滚动特效的js代码
2013/08/17 Javascript
js history对象简单实现返回和前进
2013/10/30 Javascript
jQuery中对未来的元素绑定事件用bind、live or on
2014/04/17 Javascript
Javascript 构造函数详解
2014/10/22 Javascript
JSON格式化输出
2014/11/10 Javascript
JS基于VML技术实现的五角星礼花效果代码
2015/10/26 Javascript
Bootstrap 3的box-sizing样式导致UEditor控件的图片无法正常缩放的解决方案
2016/09/15 Javascript
jQuery Easyui加载表格出错时在表格中间显示自定义的提示内容
2016/12/08 Javascript
JavaScript Ajax实现异步通信
2016/12/14 Javascript
用jQuery旋转插件jqueryrotate制作转盘抽奖
2017/02/10 Javascript
jQuery中clone()函数实现表单中增加和减少输入项
2017/05/13 jQuery
微信小程序第三方框架对比 之 wepy / mpvue / taro
2019/04/10 Javascript
详解vue的双向绑定原理及实现
2019/05/05 Javascript
vue点击按钮动态创建与删除组件功能
2019/12/29 Javascript
实现一个Vue自定义指令懒加载的方法示例
2020/06/04 Javascript
Element Tooltip 文字提示的使用示例
2020/07/26 Javascript
Vuex实现简单购物车
2021/01/10 Vue.js
详解python3中tkinter知识点
2018/06/21 Python
pandas.dataframe按行索引表达式选取方法
2018/10/30 Python
Python实现微信消息防撤回功能的实例代码
2019/04/29 Python
python使用tomorrow实现多线程的例子
2019/07/20 Python
pycharm编写spark程序,导入pyspark包的3中实现方法
2019/08/02 Python
纯CSS3实现鼠标悬停提示气泡效果
2014/02/28 HTML / CSS
世界上最大的汽车共享网站:Zipcar
2017/01/14 全球购物
物业公司采购员岗位职责
2013/12/31 职场文书
爱国主义教育演讲稿
2014/08/26 职场文书
保护地球的宣传语
2015/07/13 职场文书
单位提档介绍信
2015/10/22 职场文书
Python趣味挑战之实现简易版音乐播放器
2021/05/28 Python
python编程简单几行代码实现视频转换Gif示例
2021/10/05 Python
Vue+TypeScript中处理computed方式
2022/04/02 Vue.js