• 【js重学系列】instanceof


    在 JavaScript 中,我们通常用 typeof 判断类型,但是在判断引用类型的值时,常常会遇到一个问题:无论引用的是什么类型的对象,都会返回 "object"(当然还有 "function") 。有时候我们需要知道这个引用对象的类型是数组还是一个包装对象,这个时候 instanceof 就可以派上用场了。

    废话不多说,先来几个例子热身一下,全部都知道同学,请点击右上角的关闭按钮;模模糊糊的同学,可以继续阅读,只要掌握了原理,这些题目真的是易如反掌。

    const a = 'abc';
    console.log(a instanceof String); // ?
     
    const b = new String('abc');
    console.log(b instanceof String); // ?
    
    console.log(String instanceof String);  // ?
    console.log(Object instanceof Object);  // ?
    console.log(Function instanceof Function); // ?
    console.log(Function instanceof Object); // ?
    

    instanceof 是如何工作的

    在 MDN 上是这样描述 instanceof 的:

    instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象原型链中的任何位置

    换句话说,如果A instanceof B,那么 A 必须是一个对象,而 B 必须是一个合法的 JavaScript 函数。在这两个条件都满足的情况下:

    判断 B 的 prototype 属性指向的原型对象(B.prototype)是否在对象 A 的原型链上。

    如果在,则为 true;如果不在,则为 false。

    下面我们举一个例子一步步来说明:

    function Person() {} 
    const p1 = new Person();
     
    p1 instanceof Person; // true
    

    第一步:每一个构造函数都有一个 prototype 属性。

    第二步:这个 prototype 属性指向这个构造函数的原型对象

    第三步:通过 new 关键字,可以创建一个构造函数的实例(这里是 p1),而实例上都有一个 __proto__ 属性

    第四步:实例上的 __proto__ 属性也指向构造函数的原型对象,这样我们就可以得到一张完整的关系图了

    第五步:p1 instanceof Person ,检查 B(Person) 的 prototype 属性指向的原型对象,是否在对象 A(p1) 的原型链上。

    经过我们的一步步分解,发现 B(Person) 的 prototype 所指向的原型对象确实在 A(p1) 的原型链上,所以我们可以确定 p1 instanceof Person 一定是为 true 的。

    我们再深入一点会发现,不仅仅 p1 instanceof Persontruep1 instanceof Object 也为 true ,这又是为什么呢?

    其实,Person 的原型对象上也有一个 __proto__ 属性,而这个属性指向 Objectprototype 属性所指向的原型对象,我们可以在控制台打印一下:

    既然有这个关系,那我们再完善一下上面的图:

    通过 Person 的例子,我们知道构造函数 Object 上的 prototype 属性会指向它的原型对象:

    现在,我们要判断 p1 instanceof Object 的真假,还记得上面的定义么?我们再来一遍:

    判断 B 的 prototype 属性指向的原型对象(B.prototype)是否在对象 A 的原型链上。

    如果在,则为 true;如果不在,则为 false。

    此时,我们发现 B(Object) 的 prototype 属性所指向的原型对象依然在 A(p1) 的原型链上,所以结果为 true

    通过上面的例子我们可以知道,其实 instanceof 的原理非常简单,就是一个查找原型链的过程,所以只要你理解了原型链的相关知识,理解 instanceof 的原理就不会再有问题了。这里我们稍微总结两点与instanceof 有关的原型链知识:

    1. 所有 JavaScript 对象都有 __proto__ 属性,只有 Object.prototype.__proto__ === null
    2. 构造函数的 prototype 属性指向它的原型对象,而构造函数实例的 __proto__ 属性也指向该原型对象;
  • 相关阅读:
    让history命令 显示执行命令的时间
    实现SSH免密登录
    数据库表空间一夜之间爆满 查看最大的表却才几百M 原来是大字段对象CLOB造成的
    Python-集合的操作
    Vim使用技巧
    Linux的内部命令和外部命令
    Redis缓存穿透和雪崩
    网络编程学习一:IP地址转换函数
    每日一问15:C++中的.h,cpp以及.hpp文件
    每日一问14: 缓存和缓冲的区别
  • 原文地址:https://www.cnblogs.com/ycyc123/p/14334729.html
Copyright © 2020-2023  润新知