http://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/

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 原型继承机制。

回页首

详细剖析 ECMAScript-262 edition 3 中 instanceof 运算符的定义

语言规范对中 instanceof 运算符的定义如下:

清单 5. 规范中 instanceof 运算符定义
 11.8.6 The instanceof operator The production RelationalExpression: RelationalExpression instanceof ShiftExpression is evaluated as follows: 1. Evaluate RelationalExpression. 2. Call GetValue(Result(1)).// 调用 GetValue 方法得到 Result(1) 的值,设为 Result(2) 3. Evaluate ShiftExpression. 4. Call GetValue(Result(3)).// 同理,这里设为 Result(4) 5. If Result(4) is not an object, throw a TypeError exception.// 如果 Result(4) 不是 object,//抛出异常/* 如果 Result(4) 没有 [[HasInstance]] 方法,抛出异常。规范中的所有 [[...]] 方法或者属性都是内部的,
在 JavaScript 中不能直接使用。并且规范中说明,只有 Function 对象实现了 [[HasInstance]] 方法。
所以这里可以简单的理解为:如果 Result(4) 不是 Function 对象,抛出异常 */ 6. If Result(4) does not have a [[HasInstance]] method, throw a TypeError exception. // 相当于这样调用:Result(4).[[HasInstance]](Result(2)) 7. Call the [[HasInstance]] method of Result(4) with parameter Result(2). 8. Return Result(7). // 相关的 HasInstance 方法定义15.3.5.3 [[HasInstance]] (V) Assume F is a Function object.// 这里 F 就是上面的 Result(4),V 是 Result(2) When the [[HasInstance]] method of F is called with value V, the following steps are taken: 1. If V is not an object, return false.// 如果 V 不是 object,直接返回 false 2. Call the [[Get]] method of F with property name "prototype".// 用 [[Get]] 方法取 // F 的 prototype 属性3. Let O be Result(2).//O = F.[[Get]]("prototype") 4. If O is not an object, throw a TypeError exception. 5. Let V be the value of the [[Prototype]] property of V.//V = V.[[Prototype]] 6. If V is null, return false. // 这里是关键,如果 O 和 V 引用的是同一个对象,则返回 true;否则,到 Step 8 返回 Step 5 继续循环7. If O and V refer to the same object or if they refer to objects joined to each other (section 13.1.2), return true. 8. Go to step 5.

上面的规范定义很晦涩,而且看起来比较复杂,涉及到很多概念,但把这段规范翻译成 JavaScript 代码却很简单,如下:

清单 6. 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__; } }

回页首

JavaScript 原型继承机制

由于本文主要集中在剖析 JavaScript instanceof 运算符,所以对于 JavaScript 的原型继承机制不再做详细的讲解,下面参考来自 http://www.mollypages.org/misc/js.mp 的一张图片,此图片详细的描述了 JavaScript 各种对象的显示和隐式原型链结构。

由其本文涉及显示原型和隐式原型,所以下面对这两个概念作一下简单说明。在 JavaScript 原型继承结构里面,规范中用 [[Prototype]] 表示对象隐式的原型,在 JavaScript 中用 __proto__ 表示,并且在 Firefox 和 Chrome 浏览器中是可以访问得到这个属性的,但是 IE 下不行。所有 JavaScript 对象都有 __proto__ 属性,但只有 Object.prototype.__proto__ 为 null,前提是没有在 Firefox 或者 Chrome 下修改过这个属性。这个属性指向它的原型对象。 至于显示的原型,在 JavaScript 里用 prototype 属性表示,这个是 JavaScript 原型继承的基础知识,在这里就不在叙述了。

图 1. JavaScript 原型链

回页首

讲解 instanceof 复杂用法

有了上面 instanceof 运算符的 JavaScript 代码和原型继承图,再来理解 instanceof 运算符将易如反掌。下面将详细讲解 Object instanceof Object,Function instanceof Function 和 Foo instanceof Foo 三个示例,其它示例读者可自行推演。

清单 7. 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

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

清单 9. 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 为例。

清单 10. 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 语言中 instanceof 运算符,并且结合语言规范深入剖析了此操作符的算法。对读者使用 JavaScript 编写复杂的面向对象程序会有很大的帮助。本文所有代码在 Firefox 15 下通过测试。

参考资料

学习

  • 关于 Dojo,请参考 Dojo 官方网站
  • developerWorks Web development 专区:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。
  • developerWorks Ajax 资源中心:这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。
  • developerWorks Web 2.0 资源中心,这是有关 Web 2.0 相关信息的一站式中心,包括大量 Web 2.0 技术文章、教程、下载和相关技术资源。

转载于:https://www.cnblogs.com/lydialee/p/4868341.html

JavaScript instanceof 运算符深入剖析【转载】相关推荐

  1. JavaScript instanceof 运算符深入剖析

    简介: 随着 web 的发展,越来越多的产品功能都放在前端进行实现,增强用户体验.而前端开发的主要语言则是 JavaScript.学好 JavaScript 对开发前端应用已经越来越重要.在开发复杂产 ...

  2. JavaScript instanceof的实现

    JavaScript instanceof 运算符代码 function instance_of(L, R) {//L 表示左表达式,R 表示右表达式var O = R.prototype;// 取 ...

  3. JavaScript中的instanceof运算符是什么?

    本文翻译自:What is the instanceof operator in JavaScript? The instanceof keyword in JavaScript can be qui ...

  4. 从 JavaScript 属性描述器剖析 Vue.js 响应式视图

    学习每一门语言,一般都是从其数据结构开始,JavaScript也是一样,而JavaScript的数据结构中对象(Object)是最基础也是使用最频繁的概念和语法,坊间有言,JavaScript中,一切 ...

  5. (4)javascript的运算符以及运算符的优先级

    运算符的使用方法 在javascript的程序中要完成各种各样的运算,是离不开运算符的. 在javascript中,按运算符类型可以分为算术运算符.赋值运算符.比较运算符.逻辑运算符.条件运算符等. ...

  6. typeof和instanceof 运算符

    instanceof运算符与typeof运算符相似,都适用于检测数据类型,但是在具体细节方面还是不同的 使用typeof测试数据类型 typeof 12;//"number" ty ...

  7. Java instanceof运算符

    java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法:  re ...

  8. PHP面向对象:instanceof 运算符 (备忘)

    转载:http://www.nowamagic.net/php/php_InstanceofOperator.php 感谢分享 在PHP5中,通过方法传递变量的类型有不确定性.于是我们很难判断,一些操 ...

  9. java 访客模式,每日一课 | Java 8中的instanceof运算符和访客模式替换

    每日一课 | Java 8中的instanceof运算符和访客模式替换 每日一课 | Java 8中的instanceof运算符和访客模式替换 我有一个梦想,不再需要操作员和垂头丧气的instance ...

最新文章

  1. 国外论坛BCH关注度暴涨
  2. 三大运营商借5G消息围攻微信,就问张小龙怕不怕
  3. 快速部署-01-docker
  4. python jieba库用法
  5. android jni jstring 转 char*
  6. 【设计模式】—— 适配器模式Adapter
  7. 第二十五期:搞定Linux Shell文本处理工具,看完这篇集锦就够了
  8. 客户端调用 WCF 的几种方式
  9. SHELL脚本-猜数字游戏
  10. IMC IMV SecurityCenter连通
  11. Class 类文件结构解析
  12. code3:使用set判断数组中是否有重复值
  13. 计算机画大熊猫教案,大班美术画大熊猫教案
  14. 27 信息过滤与反垃圾
  15. c语言大学教程答案pdf,C++大学教程(第九版) 保罗·戴特尔(Paul Deitel)等著 完整中文pdf扫描版[197MB]...
  16. 过年不再被逼相亲——我用python给亲戚展示2022的相亲数据
  17. Android 使用 MediaCodec API音频播放器
  18. HTML前端(一)----DIV布局
  19. Java多线程——线程池使用示例
  20. 中国石油化工产业发展环境深度分析及投资价值评估报告2022-2028年版

热门文章

  1. ubuntu16.04下载caffe(CPU版本)及部分文件说明
  2. .NET开源MSSQL、Redis监控产品Opserver之安全配置
  3. Skeljs – 用于构建响应式网站的前端开发框架
  4. WinFormsChartSamples
  5. 分享42个精美的免费PSD素材
  6. final方法覆盖与重载问题以及不同访问权限问题
  7. 35岁的程序员,真的要转管理吗?
  8. centos 释放swap_centos6.6关闭与打开swap(整理)
  9. 7000 字,四年多 Java 的 BAT 面经分享!
  10. 百度又搞了一个“搜索”~