迹忆客 专注技术分享

当前位置:主页 > 学无止境 > WEB前端 >

为什么'[] instanceof Object'返回'true'?

作者:迹忆客 最近更新:2022/10/06 浏览次数:

我们都知道 []instanceof Array 返回true,但是为什么 []instanceof Object 也返回true呢?

朋友,如果你在面试中被问到这个问题,你会怎么回答?


什么是instanceof ?

我们来看看MDN上的解释:

“instanceofoperator 测试构造函数的原型属性是否出现在对象原型链的任何位置。 返回值是一个布尔值。 它的行为可以用 Symbol.hasInstance 来定制。”

// 来自 mdn
const Cat = function (name) {
  this.name = name
}
Cat.prototype.showName = function () {
  console.log(this.name)
}
const cat = new Cat('miao')

console.log(cat instanceof Cat) // true
view raw

那么,为什么 cat instanceof Cat 返回 true 呢? 很简单,画个图就更容易理解了。

 

instanceof Cat
instanceof Cat

 

由于 Cat.prototype 出现在 cat 的原型链上,所以返回 true 是正确的。

让我们看一个更复杂的例子:

const Animal = function (name) {
  this.name = name
}

Animal.prototype.showName = function () {
  console.log(this.name)
}

const Cat = function (name) {
  Animal.call(this, name)
}

Cat.prototype = new Animal()
Cat.prototype.constructor = Cat

const cat = new Cat('miao')

console.log(cat instanceof Cat) // true
console.log(cat instanceof Animal) // true
console.log(cat instanceof Object) // true

 

javascript instanceof more complex
javascript instanceof more complex

 

从这张图我们可以很清楚的解释为什么三个表达式都返回 true,因为 Cat.prototypeAnimal.prototypeObject.prototype 都出现在 Cat 的原型上,所以结果为true。

  1. cat instanceof Cat
  2. cat instanceof Animal
  3. cat instanceof Object

为什么 “[] instanceof Object” 返回 true

让我们回到问题本身,一起画一个简单的图来看看答案。

 

javascript instanceof object
javascript instanceof object

 

const arr = []

console.log(arr instanceof Array) // true
console.log(arr instanceof Object) // true

如何实现 instanceof 运算符?

经过上面的讲解,当面试官问我们如何实现一个 instanceof 时,掌握这些知识点就足够了。

  1. 构造函数的原型
  2. 对象的原型链

解决方法1

/**
 * 
 * @param {*} obj instance object
 * @param {*} func Constructor
 * @returns true false
 */
const instanceOf1 = (obj, func) => {
  // 它必须是对象或函数
  if (!(obj && ['object', 'function'].includes(typeof obj))) {
    return false
  }
  let proto = Object.getPrototypeOf(obj)
  if (proto === func.prototype) {
    return true
  } else if (proto === null) {
    return false
  } else {
    return instanceOf1(proto, func)
  }
}
// 做个测试
let Fn = function () { }
let p1 = new Fn()

console.log(instanceOf1({}, Object)) // true
console.log(instanceOf1(p1, Fn)) // true
console.log(instanceOf1({}, Fn)) // false
console.log(instanceOf1(null, Fn)) // false
console.log(instanceOf1(1, Fn)) // false
view raw

解决方法2

/**
 * 
 * @param {*} obj instance object
 * @param {*} func Constructor
 * @returns true false
 */
const instanceOf2 = (obj, func) => {
  // 它必须是对象或函数
  if (!(obj && ['object', 'function'].includes(typeof obj))) {
    return false
  }
  let proto = obj
  while (proto = Object.getPrototypeOf(proto)) {
    if (proto === func.prototype) {
      return true
    }
  }
  return false
}
// 做个测试
let Fn = function () { }
let p1 = new Fn()

console.log(instanceOf2({}, Object)) // true
console.log(instanceOf2(p1, Fn)) // true
console.log(instanceOf2({}, Fn)) // false
console.log(instanceOf2(null, Fn)) // false
console.log(instanceOf2(1, Fn)) // false
view raw

解决方法3

/**
 * 
 * @param {*} obj instance object
 * @param {*} func Constructor
 * @returns true false
 */
const instanceOf3 = (obj, func) => {
  // 它必须是对象或函数
  if (!(obj && ['object', 'function'].includes(typeof obj))) {
    return false
  }
  let proto = Object.getPrototypeOf(obj)
  // 因为必须有结束(最后是Object),所以不会是死循环
  while (true) {
    if (proto === null) {
      return false
    } else if (proto === func.prototype) {
      return true
    } else {
      proto = Object.getPrototypeOf(proto)
    }
  }
}
// 做个测试
let Fn = function () { }
let p1 = new Fn()

console.log(instanceOf3({}, Object)) // true
console.log(instanceOf3(p1, Fn)) // true
console.log(instanceOf3({}, Fn)) // false
console.log(instanceOf3(null, Fn)) // false
console.log(instanceOf3(1, Fn)) // false

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 Angular 中上传文件

发布时间:2023/04/14 浏览次数:71 分类:Angular

本教程演示了如何在 Angular 中上传任何文件。我们还将介绍如何在文件上传时显示进度条,并在上传完成时显示文件上传完成消息。

Angular 2 中的复选框双向数据绑定

发布时间:2023/04/14 浏览次数:139 分类:Angular

本教程演示了如何一键标记两个复选框。这篇有 Angular 的文章将着眼于执行复选框双向数据绑定的不同方法。

在 AngularJs 中加载 spinner

发布时间:2023/04/14 浏览次数:107 分类:Angular

我们将介绍如何在请求加载时添加加载 spinner,并在 AngularJs 中加载数据时停止加载器。

在 Angular 中显示和隐藏

发布时间:2023/04/14 浏览次数:78 分类:Angular

本教程演示了 Angular 中的显示和隐藏。在开发商业应用程序时,我们需要根据用户角色或条件隐藏一些数据。我们必须根据该应用程序中的条件显示相同的数据。

在 Angular 中下载文件

发布时间:2023/04/14 浏览次数:104 分类:Angular

本教程演示了如何在 angular 中下载文件。我们将介绍如何通过单击按钮在 Angular 中下载文件并显示一个示例。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便