资讯专栏INFORMATION COLUMN

"instanceof 的原理是什么"?大声告诉面试官,我知道!

CompileYouth / 1757人阅读

摘要:一是如何工作的在上是这样描述的运算符用于测试构造函数的属性是否出现在对象原型链中的任何位置换句话说,如果,那么必须是一个对象,而必须是一个合法的函数。下面我们举一个例子一步步来说明第一步每一个构造函数都有一个属性。

在 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 有关的原型链知识:

所有 JavaScript 对象都有 __proto__ 属性,只有 Object.prototype.__proto__ === null

构造函数的 prototype 属性指向它的原型对象,而构造函数实例的 __proto__ 属性也指向该原型对象;

二、如何实现一个 instanceof ?

看了上面的过程,其实也很容易给出 instanceof 的实现方式:

function instance_of(left, right) {
  const RP = right.prototype; // 构造函数的原型
  while(true) {
    if (left === null) {
      return false;
    }
    if (left === RP) { // 一定要严格比较
      return true;
    }
    left = left.__proto__; // 沿着原型链重新赋值
  }
}

有了上面的实现方法,我们再解释一下上面的例子:

function Person() {}
const p1 = new Person();
p1 instanceof Object; // 用上面的代码解释它

第一次赋值

left = p1
right = Object
RP = Object.prototype

第一次判断

left !== null 并且 left !== RP ,继续向上寻找 left 的原型链,准备新的赋值。

第二次赋值

left = p1.__proto__ = Person.prototype

第二次判断

left !== null 并且 left !== RP ,继续向上寻找 left 的原型链,准备新的赋值。

第三次赋值

left = p1.__proto__.__proto__ = Person.prototype.__proto__

第三次赋值

left !== null ,此时 left === RP ,返回 true ,函数执行完毕。

三、总结

今天,我们用一个例子,通过画图以及代码实现两个角度剖析了 instanceof 的实现原理,其实思路也很简单,无非就是一个沿原型链向上查找的过程。希望大家可以在以后的面试过程中,不再被" instanceof 的实现原理是什么?"这样的面试难住了。

当然,阅读永远都只是一种十分被动的学习方法,我还是建议你能自己实践一下。在文章的开头有几个例子,感兴趣的同学可以挑选一个例子,自己通过画图以及代码实现两种方式再加深一遍理解,相信你会理解的更深刻。

如果文章中错误或表述不严谨的地方,欢迎指正。

最后,文章会首先发布在我的 Github ,以及公众号上,欢迎关注。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103544.html

相关文章

  • 互联网"凛冬",看大厂HR怎么说~

    摘要:写在前面的话最近互联网朋友圈充斥着一股恐慌的气息。本人作为一名,万不敢称资深,只是呆过几年大型央企和大型互联网企业,聊有一点自己的看法罢了。如果不放心,以一周为期,对展示在面前的机会进行初步分级。也可以略高于期望,以此探一探对方的反应。 showImg(https://segmentfault.com/img/bVblxeY?w=1008&h=298); 写在前面的话   最近互联网朋...

    renweihub 评论0 收藏0
  • 如何"有计划,高效率,优简历"应对面试

    摘要:虽然有了十全的计划,但如何高效率去记住上面那么多东西是一个大问题,看看我是怎么做的。 前言 前一篇文章讲述了我在三月份毫无准备就去面试的后果,一开始心态真的爆炸,但是又不服气,一想到每次回来后家人朋友问我面试结果的期待脸,越觉得必须付出的行动来证明自己了。 面经传送门:一个1年工作经验的PHP程序员是如何被面试官虐的? 下面是我花费两个星期做的准备,主要分三部分: 有计划——计划好...

    gyl_coder 评论0 收藏0
  • "双非"应届生校招如何获得大厂青睐?(内附前端大厂面经+技术岗超全求职攻略)

    摘要:拿到秋招的同学,如确定入职需与用人单位签署三方协议,以保证双方的利益不受损失。当然每个岗位所要求的侧重点不同,但却百变不离其宗。方法论要想达成某个目标都有其特定的方法论,学习技术也不例外,掌握适当的学习方法才能事半功倍。 写在前面的话 笔者从17年的2月份开始准备春招,其中遇到不少坑,也意识到自己走过的弯路。故写了这篇文章总结一番,本文适合主动学习的,对自己要学的课程不明确的,对面试有...

    jeffrey_up 评论0 收藏0
  • "双非"应届生校招如何获得大厂青睐?(内附前端大厂面经+技术岗超全求职攻略)

    摘要:拿到秋招的同学,如确定入职需与用人单位签署三方协议,以保证双方的利益不受损失。当然每个岗位所要求的侧重点不同,但却百变不离其宗。方法论要想达成某个目标都有其特定的方法论,学习技术也不例外,掌握适当的学习方法才能事半功倍。 写在前面的话 笔者从17年的2月份开始准备春招,其中遇到不少坑,也意识到自己走过的弯路。故写了这篇文章总结一番,本文适合主动学习的,对自己要学的课程不明确的,对面试有...

    lindroid 评论0 收藏0
  • 女朋友做软件测试 人很好 很阳光 有点调皮 但也很严肃 对了厨艺可一级棒哟!爱她只 她喜欢

    摘要:所以要告诉她,等她回来后我指定比以前更爱她,我一直想告诉她,我比她想象中要更爱她。以后的生活就轻松很多。等到完成之后再回顾这一段路程的时候,你肯定会感慨良多。 她呀...

    娣辩孩 评论0 收藏0

发表评论

0条评论

CompileYouth

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<