解析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 相关文章推荐
JS操作Cookies包括(读取添加与删除)
Dec 26 Javascript
js使浏览器窗口最大化实现代码(适用于IE)
Aug 07 Javascript
js简单实现让文本框内容逐个字的显示出来
Oct 22 Javascript
为开发者准备的10款最好的jQuery日历插件
Feb 04 Javascript
checkbox勾选判断代码分析
Jun 11 Javascript
jQuery调取jSon数据并展示的方法
Jan 29 Javascript
node.js中 stream使用教程
Aug 28 Javascript
利用jQuery实现打字机字幕效果实例代码
Sep 02 Javascript
微信小程序 css使用技巧总结
Jan 09 Javascript
原生js实现简单的Ripple按钮实例代码
Mar 24 Javascript
ES6学习教程之块级作用域详解
Oct 09 Javascript
webpack多页面开发实践
Dec 18 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
咖啡是不是喝了会上瘾?咖啡是必须品吗!
2021/03/04 新手入门
php查看网页源代码的方法
2015/03/13 PHP
IE和Mozilla的兼容性汇总event
2007/08/12 Javascript
jquery next nextAll nextUntil siblings的区别介绍
2013/10/05 Javascript
JavaScript对内存分配及管理机制详细解析
2013/11/11 Javascript
表单提交前触发函数返回true表单才会提交
2014/03/11 Javascript
javascript将相对路径转绝对路径示例
2014/03/14 Javascript
js获取元素外链样式的方法
2015/01/27 Javascript
JavaScript+html5 canvas制作的圆中圆效果实例
2016/01/27 Javascript
JS中innerHTML和pasteHTML的区别实例分析
2016/06/22 Javascript
Node.js开启Https的实践详解
2016/10/25 Javascript
Centos7 中安装 Node.js v4.4.4
2016/11/03 Javascript
Angularjs单选框相关的示例代码
2017/08/17 Javascript
json2.js 入门教程之使用方法与实例分析
2017/09/14 Javascript
jfinal与bootstrap的登出实战详解
2017/11/27 Javascript
create-react-app构建项目慢的解决方法
2018/03/14 Javascript
node中modules.exports与exports导出的区别
2018/06/08 Javascript
基于vue实现移动端圆形旋钮插件效果
2018/11/28 Javascript
python读取html中指定元素生成excle文件示例
2014/04/03 Python
python网络编程学习笔记(五):socket的一些补充
2014/06/09 Python
Python标准库与第三方库详解
2014/07/22 Python
Python无损音乐搜索引擎实现代码
2018/02/02 Python
python Opencv将图片转为字符画
2021/02/19 Python
Python常见字典内建函数用法示例
2018/05/14 Python
python顺序执行多个py文件的方法
2019/06/29 Python
如何不用安装python就能在.NET里调用Python库
2019/07/12 Python
Python的几种主动结束程序方式
2019/11/22 Python
python 用opencv实现霍夫线变换
2020/11/27 Python
html5 input属性使用示例
2013/06/28 HTML / CSS
深入探究HTML5的History API
2015/07/09 HTML / CSS
HTML5实现视频弹幕功能
2019/08/09 HTML / CSS
诺思信科技(南京)有限公司.NET笔试题答案
2013/07/06 面试题
最新会计专业求职信范文
2014/01/28 职场文书
创建青年文明号材料
2014/05/09 职场文书
学生吸烟检讨书
2014/09/14 职场文书
户外拓展训练感想
2015/08/07 职场文书