实例讲解JavaScript中instanceof运算符的用法


Posted in Javascript onJune 08, 2016

instanceof 运算符简介

在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 “object”。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。例如:

清单 1. instanceof 示例

var oStringObject = new String("hello world"); 
 console.log(oStringObject instanceof String); // 输出 "true"

这段代码问的是“变量 oStringObject 是否为 String 对象的实例?”oStringObject 的确是 String 对象的实例,因此结果是”true”。尽管不像 typeof 方法那样灵活,但是在 typeof 方法返回 “object” 的情况下,instanceof 方法还是很有用的。

instanceof 运算符的常规用法:

通常来讲,使用 instanceof 就是判断一个实例是否属于某种类型。例如:

清单 2. instanceof 常规用法

// 判断 foo 是否是 Foo 类的实例
 function Foo(){} 
 var foo = new Foo(); 
 console.log(foo instanceof Foo)//true

另外,更重的一点是 instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型。例如:

清单 3. instanceof 在继承中关系中的用法

// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
 function Aoo(){} 
 function Foo(){} 
 Foo.prototype = new Aoo();//JavaScript 原型继承
 
 var foo = new Foo(); 
 console.log(foo instanceof Foo)//true 
 console.log(foo instanceof Aoo)//true

上面的代码中是判断了一层继承关系中的父类,在多层继承关系中,instanceof 运算符同样适用。

你真的了解 instanceof 操作符吗?

看了上面的代码示例,是不是觉得 instanceof 操作符很简单,下面来看点复杂的用法。

清单 4. instanceof 复杂用法

console.log(Object instanceof Object);//true 
 console.log(Function instanceof Function);//true 
 console.log(Number instanceof Number);//false 
 console.log(String instanceof String);//false 
 
 console.log(Function instanceof Object);//true 
 
 console.log(Foo instanceof Function);//true 
 console.log(Foo instanceof Foo);//false

看了上面的代码是不是又晕头转向了?为什么 Object 和 Function instanceof 自己等于 true,而其他类 instanceof 自己却又不等于 true 呢?如何解释?要想从根本上了解 instanceof 的奥秘,需要从两个方面着手:1,语言规范中是如何定义这个运算符的。2,JavaScript 原型继承机制。

清单 5. JavaScript instanceof 运算符代码

function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
 var O = R.prototype;// 取 R 的显示原型
 L = L.__proto__;// 取 L 的隐式原型
 while (true) { 
 if (L === null) 
 return false; 
 if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true 
 return true; 
 L = L.__proto__; 
 } 
 }

清单 6. Object instanceof Object

// 为了方便表述,首先区分左侧表达式和右侧表达式
 ObjectL = Object, ObjectR = Object; 
 // 下面根据规范逐步推演
 O = ObjectR.prototype = Object.prototype 
 L = ObjectL.__proto__ = Function.prototype 
 // 第一次判断
 O != L 
 // 循环查找 L 是否还有 __proto__ 
 L = Function.prototype.__proto__ = Object.prototype 
 // 第二次判断
 O == L 
 // 返回 true

清单 7. Function instanceof Function

// 为了方便表述,首先区分左侧表达式和右侧表达式
 FunctionL = Function, FunctionR = Function; 
 // 下面根据规范逐步推演
 O = FunctionR.prototype = Function.prototype 
 L = FunctionL.__proto__ = Function.prototype 
 // 第一次判断
 O == L 
 // 返回 true

清单 8. Foo instanceof Foo

// 为了方便表述,首先区分左侧表达式和右侧表达式
 FooL = Foo, FooR = Foo; 
 // 下面根据规范逐步推演
 O = FooR.prototype = Foo.prototype 
 L = FooL.__proto__ = Function.prototype 
 // 第一次判断
 O != L 
 // 循环再次查找 L 是否还有 __proto__ 
 L = Function.prototype.__proto__ = Object.prototype 
 // 第二次判断
 O != L 
 // 再次循环查找 L 是否还有 __proto__ 
 L = Object.prototype.__proto__ = null 
 // 第三次判断
 L == null 
 // 返回 false

简析 instanceof 在 Dojo 继承机制中的应用

在 JavaScript 中,是没有多重继承这个概念的,就像 Java 一样。但在 Dojo 中使用 declare 声明类时,是允许继承自多个类的。下面以 Dojo 1.6.1 为例。

清单 9. Dojo 中多重继承

dojo.declare("Aoo",null,{}); 
 dojo.declare("Boo",null,{}); 
 dojo.declare("Foo",[Aoo,Boo],{}); 
 
 var foo = new Foo(); 
 console.log(foo instanceof Aoo);//true 
 console.log(foo instanceof Boo);//false 
 
 console.log(foo.isInstanceOf(Aoo));//true 
 console.log(foo.isInstanceOf(Boo));//true

上面的示例中,Foo 同时继承自 Aoo 和 Boo,但当使用 instanceof 运算符来检查 foo 是否是 Boo 的实例时,返回的是 false。实际上,在 Dojo 的内部,Foo 仍然只继承自 Aoo,而通过 mixin 机制把 Boo 类中的方法和属性拷贝到 Foo 中,所以当用 instanceof 运算符来检查是否是 Boo 的实例时,会返回 false。所以 Dojo 为每个类的实例添加了一个新的方法叫 isInstanceOf,用这个方法来检查多重继承。

Javascript 相关文章推荐
一段实现页面上的图片延时加载的js代码
Feb 11 Javascript
jquery 模拟类搜索框自动完成搜索提示功能(改进)
May 24 Javascript
JavaScript字符串插入、删除、替换函数使用示例
Jul 25 Javascript
JS+flash实现chrome和ie浏览器下同时可以复制粘贴
Sep 22 Javascript
Jquery1.9.1源码分析系列(十五)动画处理之外篇
Dec 04 Javascript
JS实现点击登录弹出窗口同时背景色渐变动画效果
Mar 25 Javascript
javascript制作照片墙及制作过程中出现的问题
Apr 04 Javascript
ES6新特性之模块Module用法详解
Apr 01 Javascript
使用use注册Vue全局组件和全局指令的方法
Mar 08 Javascript
angular将html代码输出为内容的实例
Sep 30 Javascript
微信小程序页面滚动到指定位置代码实例
Sep 07 Javascript
原生js实现的金山打字小游戏(实例代码详解)
Mar 16 Javascript
js获取对象、数组的实际长度,元素实际个数的实现代码
Jun 08 #Javascript
JS & JQuery 动态添加 select option
Jun 08 #Javascript
Jquery ajax请求导出Excel表格的实现代码
Jun 08 #Javascript
浅谈几种常用的JS类定义方法
Jun 08 #Javascript
浅谈javascript中的constructor
Jun 08 #Javascript
js定义类的几种方法(推荐)
Jun 08 #Javascript
JavaScript必知必会(七)js对象继承
Jun 08 #Javascript
You might like
PHP产生随机字符串函数
2006/12/06 PHP
POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)
2010/10/12 PHP
PHP的范围解析操作符(::)的含义分析说明
2011/07/03 PHP
php将mysql数据库整库导出生成sql文件的具体实现
2014/01/08 PHP
php 查找数组元素提高效率的方法详解
2017/05/05 PHP
PHP实现APP微信支付的实例讲解
2018/02/10 PHP
jquery html动态生成select标签出问题的解决方法
2013/11/20 Javascript
jquery toolbar与网页浮动工具条具体实现代码
2014/01/12 Javascript
js实现对table动态添加、删除和更新的方法
2015/02/10 Javascript
JavaScript实现仿淘宝商品购买数量的增减效果
2016/01/22 Javascript
JavaScript——DOM操作——Window.document对象详解
2016/07/14 Javascript
总结AngularJS开发者最常犯的十个错误
2016/08/31 Javascript
angular双向绑定模拟探索
2016/12/26 Javascript
AngularJS之ionic 框架下实现 Localstorage本地存储
2017/04/22 Javascript
Nodejs回调加超时限制两种实现方法
2017/06/09 NodeJs
分享ES6的7个实用技巧
2018/01/18 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
微信小程序利用canvas 绘制幸运大转盘功能
2018/07/06 Javascript
详解vue-cli下ESlint 配置说明
2018/09/03 Javascript
vuex分模块后,实现获取state的值
2020/07/26 Javascript
解决VUE项目localhost端口服务器拒绝连接,只能用127.0.0.1的问题
2020/08/14 Javascript
json.stringify()与json.parse()的区别以及用处
2021/01/25 Javascript
python实现文本去重且不打乱原本顺序
2016/01/26 Python
ubuntu系统下 python链接mysql数据库的方法
2017/01/09 Python
Python获取当前页面内所有链接的四种方法对比分析
2017/08/19 Python
Jacques Lemans德国:奥地利钟表品牌
2019/12/26 全球购物
C#里面如何判断一个Object是否是某种类型(如Boolean)?
2016/02/10 面试题
办理护照介绍信
2014/01/16 职场文书
剪枝的学问教学反思
2014/02/07 职场文书
食品安全工作方案
2014/05/07 职场文书
优秀本科毕业生自荐信
2014/07/04 职场文书
2014年前台接待工作总结
2014/12/05 职场文书
教师工作决心书
2015/02/04 职场文书
2015年高一班主任工作总结
2015/05/13 职场文书
解决go在函数退出后子协程的退出问题
2021/04/30 Golang
MySQL官方导出工具mysqlpump的使用
2021/05/21 MySQL