解析JavaScript中instanceof对于不同的构造器或许都返回true


Posted in Javascript onDecember 03, 2013

我们知道 instanceof 运算符用来检查对象是否为某构造器的实例。下面列举它返回true的各种情景。

1、对象obj是通过new Constructor创建的,那么 obj instanceof Constructor 为true

function Person(n, a) { 
    this.name = n; 
    this.age = a; 
} 
var p = new Person('John Backus', 82); 
console.log(p instanceof Person); // true

2、如果存在继承关系,那么 子类实例 instanceof 父类 也会返回true
function A(){} 
function B(){} 
B.prototype = new A(); // B继承于A var b = new B(); 
console.log(b instanceof A); // true

3、由于Object是根类,所有其它自定义类都继承于它,因此 任意构造器的实例 instanceof Object 都返回true
function A() {} 
var a = new A(); 
console.log(a instanceof Object); // true var str = new String('hello'); 
console.log(str instanceof Object); // true 
var num = new Number(1); 
console.log(num instanceof Object); // true

甚至包括构造器自身
function A() {} 
console.log(A instanceof Object); // true 
console.log(String instanceof Object); // true 
console.log(Number instanceof Object); // true

4、所有构造器 instanceof Function 返回true
function A() {} 
console.log(A instanceof Function); // true 
console.log(String instanceof Function); // true 
console.log(Number instanceof Function); // true

以上四点总结为一句话:如果某实例是通过某类或其子类的创建的,那么instanceof就返回true。或者说某构造函数的原型 存在与对象obj的内部原型链上,那么返回true。即instanceof的结果与构造器自身并无直接关系。这在许多语言中都是通用的。

Java中定义了一个类Person,实例p对于Person和Object都返回true

class Person { 
    public String name; 
    public int age; 
    Person (String n, int a) { 
        this.name = name; 
        this.age = a; 
    } 
    public static void main(String[] args) { 
        Person p = new Person("John Backus", 82); 
        System.out.println(p instanceof Person); // true 
        System.out.println(p instanceof Object); // true 
    } 
}

Java中如果存在继承关系,那么 子类实例 instanceof 父类 也返回true
// 父类 
class Person { 
    public String name; 
    public int age; 
    Person (String n, int a) { 
        name = name; 
        age = a; 
    } 
} 
// 子类 
public class Man extends Person{ 
    public String university; 
    Man(String n, int a, String s) { 
        super(n, a); 
        university = s; 
    } 
    public static void main(String[] args) { 
        Man mm = new Man("John Resig", 29, "PKU"); 
        System.out.println(mm instanceof Man); // true 
        System.out.println(mm instanceof Person); // 也是true 
    } 
}

知道了这些,JS中以下的表现就不奇怪了
// 定义两个构造器 
function A(){} 
function B(){} 
A.prototype = B.prototype = {a: 1}; // 分别创建两个不同构造器的实例 
var a = new A(); 
var b = new B(); 
console.log(a instanceof B); // true 
console.log(b instanceof A); // true

我们看到a, b分别是用A和B创建的,但a instanceof B和 b instanceof A都是true。即a虽然不是用构造器B创建的,但仍然返回true。因为B.prototype存在于a的内部原型链上。

由于JS的动态语言特性,可以在运行时修改原型,因此下面返回false也不足为奇了。因为A.prototype已经不在a的内部原型链中,链条被打断了。

function A(){} 
var a = new A(); 
A.prototype = {}; // 动态修改原型,注意必须在创建a后 
console.log(a instanceof A); // false

注意这么写也打破了上面总结的第一条:对象obj是通过new Constructor创建的,那么obj instanceof Constructor 为true

实际在ECMAScript标准中(以5.1为准),instanceof 内部实现会调用构造器的内部方法[[HasInstance]],描述如下

解析JavaScript中instanceof对于不同的构造器或许都返回true

假如F是一个函数对象,当F(V)执行时,以下步骤将发生:

1、如果instanceof左运算元V不是对象类型,直接返回false

var a, b = 1, c = true, d = 'hello'; 
console.log(a instanceof Object); // false 这里a值为undefined 
console.log(b instanceof Object); // false 
console.log(c instanceof Object); // false 
console.log(d instanceof Object); // false

2/3、取构造器F的prototype属性,如果不是对象类型,须抛出TypeError异常,
function A(){} 
A.prototype = 1; // A的prototype设为非对象类型 
var a = new A(); 
console.log(a instanceof A);

各浏览器抛出的异常提示不同,

Firefox18:

解析JavaScript中instanceof对于不同的构造器或许都返回true

Chrome24:

解析JavaScript中instanceof对于不同的构造器或许都返回true

Safari6:

解析JavaScript中instanceof对于不同的构造器或许都返回true

Opera12:

解析JavaScript中instanceof对于不同的构造器或许都返回true

IE10:

解析JavaScript中instanceof对于不同的构造器或许都返回true

4、不断的执行以下逻辑:将V设为内部原型的V,如果V是null则返回false,如果V和O都指向同一个对象,则返回true。

Javascript 相关文章推荐
javascript获得CheckBoxList选中的数量
Oct 27 Javascript
利用JS重写Cognos右键菜单的实现代码
Apr 11 Javascript
JSON字符串转JSON对象
Jul 31 Javascript
jquery实现动画菜单的左右滚动、渐变及图形背景滚动等效果
Aug 25 Javascript
jquery表单插件Autotab使用方法详解
Jun 24 Javascript
微信小程序开发之视频播放器 Video 弹幕 弹幕颜色自定义实例
Dec 08 Javascript
使用jQuery实现页面定时弹出广告效果
Aug 24 jQuery
利用JS测试目标网站的打开响应速度
Dec 01 Javascript
在Vue中使用icon 字体图标的方法
Jun 14 Javascript
vue点击当前路由高亮小案例
Sep 26 Javascript
laravel实现中文和英语互相切换的例子
Sep 30 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
Feb 26 Javascript
探讨JavaScript中声明全局变量三种方式的异同
Dec 03 #Javascript
解析JavaScript中delete操作符不能删除的对象
Dec 03 #Javascript
解析Javascript小括号“()”的多义性
Dec 03 #Javascript
解析Javascript中中括号“[]”的多义性
Dec 03 #Javascript
jquery将一个表单序列化为一个对象的方法
Dec 02 #Javascript
jQuery获得内容和属性方法及示例
Dec 02 #Javascript
jquery如何实现锚点链接之间的平滑滚动
Dec 02 #Javascript
You might like
用PHP程序实现支持页面后退的两种方法
2008/06/30 PHP
php 删除cookie和浏览器重定向
2009/03/16 PHP
PHP和javascript常用正则表达式及用法实例
2014/07/01 PHP
PHP的介绍以及优势详细分析
2019/09/05 PHP
Javascript 复制数组实现代码
2009/11/26 Javascript
firefox插件Firebug的使用教程
2010/01/02 Javascript
jQuery点击tr实现checkbox选中的方法
2013/03/19 Javascript
jQuery的$.proxy()应用示例介绍
2014/04/03 Javascript
解析JavaScript中的字符串类型与字符编码支持
2016/06/24 Javascript
详解Node.js中的事件机制
2016/09/22 Javascript
jQuery中$.ajax()方法参数解析
2016/10/22 Javascript
JavaScript数组去重的几种方法效率测试
2016/10/23 Javascript
bootstrap实现动态进度条效果
2017/03/08 Javascript
详解vue-resource promise兼容性问题
2017/06/20 Javascript
使用Node.js实现RESTful API的示例
2017/08/01 Javascript
阿里大于短信验证码node koa2的实现代码(最新)
2017/09/07 Javascript
JS 使用 window对象的print方法实现分页打印功能
2018/05/16 Javascript
vue配置接口域名方法总结
2019/05/12 Javascript
详解Vue.js中引入图片路径的几种方式
2019/06/17 Javascript
vue.js this.$router.push获取不到params参数问题
2020/03/03 Javascript
原生JavaScript实现购物车
2021/01/10 Javascript
pandas数据清洗,排序,索引设置,数据选取方法
2018/05/18 Python
从DataFrame中提取出Series或DataFrame对象的方法
2018/11/10 Python
Pycharm插件(Grep Console)自定义规则输出颜色日志的方法
2020/05/27 Python
html5的画布canvas——画出简单的矩形、三角形实例代码
2013/06/09 HTML / CSS
洲际酒店集团大中华区:IHG中国
2016/08/17 全球购物
物业管理大学生个人的自我评价
2013/10/10 职场文书
党的群众路线教育实践活动个人自我剖析材料
2014/10/07 职场文书
2014年幼儿园工作总结
2014/11/10 职场文书
员工离职感谢信
2015/01/22 职场文书
2015年司法局工作总结
2015/05/22 职场文书
2015国庆节66周年标语
2015/07/30 职场文书
《卖火柴的小女孩》教学反思
2016/02/19 职场文书
先进基层党组织事迹材料2016
2016/02/29 职场文书
Java8中Stream的一些神操作
2021/11/02 Java/Android
如何使用SQL Server语句创建表
2022/04/12 SQL Server