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

我们都知道 []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 Object'返回'true'?
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

 

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

 

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

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

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

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

 

为什么'[] instanceof Object'返回'true'?
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
免责声明:
1.本站所有内容由本站原创、网络转载、消息撰写、网友投稿等几部分组成。
2.本站原创文字内容若未经特别声明,则遵循协议CC3.0共享协议,转载请务必注明原文链接。
3.本站部分来源于网络转载的文章信息是出于传递更多信息之目的,不意味着赞同其观点。
4.本站所有源码与软件均为原作者提供,仅供学习和研究使用。
5.如您对本网站的相关版权有任何异议,或者认为侵犯了您的合法权益,请及时通知我们处理。
火焰兔 » 为什么'[] instanceof Object’返回’true’?