解析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 相关文章推荐
jQuery jqgrid 对含特殊字符json 数据的 Java 处理方法
Jan 01 Javascript
Underscore.js 的模板功能介绍与应用
Dec 24 Javascript
使用indexOf等在JavaScript的数组中进行元素查找和替换
Sep 18 Javascript
jQuery Validate 验证,校验规则写在控件中的具体实例
Feb 27 Javascript
js读取并解析JSON类型数据的方法
Nov 14 Javascript
jquery 重写 ajax提交并判断权限后 使用load方法报错解决方法
Jan 19 Javascript
javascript实现延时显示提示框特效代码
Apr 27 Javascript
AngularJS 避繁就简的路由
Jul 01 Javascript
原生js jquery ajax请求以及jsonp的调用方法
Aug 04 jQuery
vuex的简单使用教程
Feb 02 Javascript
javascript简单实现深浅拷贝过程详解
Oct 08 Javascript
JS获取一个字符串中指定字符串第n次出现的位置
Feb 10 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
乐信RP2100的电路分析和打磨
2021/03/02 无线电
PHP中file_get_contents函数抓取https地址出错的解决方法(两种方法)
2015/09/22 PHP
PHP实现的简单留言板功能示例【基于thinkPHP框架】
2018/12/07 PHP
使用tp框架和SQL语句查询数据表中的某字段包含某值
2019/10/18 PHP
php设计模式之迭代器模式实例分析【星际争霸游戏案例】
2020/04/07 PHP
静态页面的值传递(三部曲)
2006/09/25 Javascript
使用Jquery搭建最佳用户体验的登录页面之记住密码自动登录功能(含后台代码)
2011/07/10 Javascript
教你如何在 Javascript 文件里使用 .Net MVC Razor 语法
2014/07/23 Javascript
jQuery幻灯片特效代码分享--鼠标滑过按钮时切换(2)
2020/11/18 Javascript
jQuery 插件封装的方法
2016/11/16 Javascript
浅谈Vue.js应用的四种AJAX请求数据模式
2017/08/30 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
解析Json字符串的三种方法日常常用
2018/05/02 Javascript
node 文件上传接口的转发的实现
2019/09/23 Javascript
js+canvas实现画板功能
2020/09/13 Javascript
Map与WeakMap类型在JavaScript中的使用详解
2020/11/18 Javascript
[02:09]DOTA2辉夜杯 EHOME夺冠举杯现场
2015/12/28 DOTA
[58:15]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 NB vs Liquid
2018/04/02 DOTA
python实现外卖信息管理系统
2018/01/11 Python
Python内置模块ConfigParser实现配置读写功能的方法
2018/02/12 Python
python使用筛选法计算小于给定数字的所有素数
2018/03/19 Python
在NumPy中创建空数组/矩阵的方法
2018/06/15 Python
基于python连接oracle导并出数据文件
2020/04/28 Python
AmazeUI 单选框和多选框的实现示例
2020/08/18 HTML / CSS
Urban Outfitters美国官网:美国生活方式品牌
2016/08/26 全球购物
adidas旗下高尔夫装备供应商:TaylorMade Golf(泰勒梅高尔夫)
2016/08/28 全球购物
经理秘书岗位职责
2013/11/14 职场文书
广告词串烧
2014/03/19 职场文书
车辆工程专业求职信
2014/04/28 职场文书
婚纱店策划方案
2014/05/22 职场文书
2014年外联部工作总结
2014/11/17 职场文书
2014年社区矫正工作总结
2014/11/18 职场文书
争先创优个人总结
2015/03/04 职场文书
​(迎国庆)作文之我爱我的祖国
2019/09/19 职场文书
Python matplotlib可视化之绘制韦恩图
2022/02/24 Python
TV动画《八十龟酱观察日记》第四季宣传PV公布
2022/04/06 日漫