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 相关文章推荐
jquery中加载图片自适应大小主要实现代码
Aug 23 Javascript
今天抽时间给大家整理jquery和ajax的相关知识
Nov 17 Javascript
Svg.js实例教程及使用手册详解(一)
May 16 Javascript
使用Bootstrap框架制作查询页面的界面实例代码
May 27 Javascript
Vue.js第四天学习笔记(组件)
Dec 02 Javascript
AngularJs中Bootstrap3 datetimepicker使用实例
Dec 13 Javascript
jQuery zTree树插件简单使用教程
Jan 10 Javascript
基于js文件加载优化(详解)
Jan 03 Javascript
AngularJS实现的2048小游戏功能【附源码下载】
Jan 03 Javascript
bootstrap模态框弹出和隐藏,动态改变中间内容的实例
Aug 10 Javascript
详解微信小程序开发之formId使用(模板消息)
Aug 27 Javascript
小程序实现文字循环滚动动画
Jun 14 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+xslt在windows平台上
2006/10/09 PHP
如何在PHP中使用Oracle数据库(2)
2006/10/09 PHP
DISCUZ 论坛管理员密码忘记的解决方法
2009/05/14 PHP
PHP查询数据库中满足条件的记录条数(两种实现方法)
2013/01/29 PHP
解析PHP汉字转换拼音的类
2013/06/18 PHP
CodeIgniter针对lighttpd服务器URL重写的方法
2015/06/10 PHP
PHP魔术方法的使用示例
2015/06/23 PHP
学习php设计模式 php实现访问者模式(Visitor)
2015/12/07 PHP
PHP获取网页所有连接的方法(附demo源码下载)
2016/03/30 PHP
laravel 获取当前url的别名方法
2019/10/11 PHP
Jquery常用技巧收集整理篇
2010/11/14 Javascript
jquery延迟加载外部js实现代码
2013/01/11 Javascript
js重写alert控件(适合学习js的新手朋友)
2014/08/24 Javascript
全面解析Javascript无限添加QQ好友原理
2016/06/15 Javascript
原生JavaScript实现精美的淘宝轮播图效果示例【附demo源码下载】
2017/05/27 Javascript
bootstrap treeview 扩展addNode方法动态添加子节点的方法
2017/11/21 Javascript
不得不知的ES6小技巧
2018/07/28 Javascript
JS实现将对象转化为数组的方法分析
2019/01/21 Javascript
vue3.0中使用postcss-pxtorem的具体方法
2019/11/20 Javascript
vue实现自定义多选按钮
2020/07/16 Javascript
python编写Logistic逻辑回归
2020/12/30 Python
TensorFlow saver指定变量的存取
2018/03/10 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
2021/01/21 Python
css3的动画特效之动画序列(animation)
2017/12/22 HTML / CSS
Stutterheim瑞典:瑞典高级外套时装品牌
2019/06/24 全球购物
应届大学毕业生找工作的求职信范文
2013/11/29 职场文书
家长会学生演讲稿
2014/04/26 职场文书
征兵宣传标语
2014/06/20 职场文书
会计专业应届生自荐信
2014/06/28 职场文书
我的中国梦演讲稿300字
2014/08/19 职场文书
房屋认购协议书
2015/01/29 职场文书
办公室岗位职责
2015/02/04 职场文书
酒桌上的开场白
2015/06/01 职场文书
办公室规章制度范本
2015/08/04 职场文书
高二化学教学反思
2016/02/22 职场文书
Python机器学习之底层实现KNN
2021/06/20 Python