# ❓有以下 3 个判断数组的方法,请分别介绍它们之间的区别和优劣

Object.prototype.toString.call() 、 instanceof 以及 Array.isArray()

  1. Object.prototype.toString.call() 每一个继承 Object 的对象都有 toString 方法,如果 toString 方法没有重写的话,会返回[Object type],其中 type 为对象的类型。但当除了 Object 类型的对象外,其他类型直接使用 toString 方法时,会直接返回都是内容的字符串,所以我们需要使用 call 或者 apply 方法来改变 toString 方法的执行上下文。

    const jeff = ['Hello', 'world']
    jeff.toString() // "Hello,world"
    Object.prototype.toString.call(jeff) // "[object Array]"
    
    1
    2
    3

    对所有的类型都可以判断,包括 null undefined symbol

    Object.prototype.toString.call('Jeff') // "[object String]"
    Object.prototype.toString.call(1) // "[object Number]"
    Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
    Object.prototype.toString.call(null) // "[object Null]"
    Object.prototype.toString.call(undefined) // "[object Undefined]"
    Object.prototype.toString.call(function() {}) // "[object Function]"
    Object.prototype.toString.call({ name: 'Jeff' }) // "[object Object]"
    
    1
    2
    3
    4
    5
    6
    7
  2. instanceof

    instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

    那么使用 instanceof 判断一个对象是否为 Array,就是检测这个实例对象的原型链上面是否有 Array 的 prototype 属性。找到就返回 true

    ;[] instanceof Array // true
    
    1

    需要注意的是 instanceof 只能用来判断对象的属性,而且,所有的对象都 instanceof Object 都是 true

    'Jeff' instanceof String // false 检查原型链会找到 undefined
    new String('Jeff') instanceof String // true
    
    [] instanceof Object // true
    
    Object.create(null) instanceof Object // false 一种创建非 Object 实例的对象的方法
    
    1
    2
    3
    4
    5
    6
  3. Array.isArray()

    用于确定传递的值是否是一个 Array

    当检测 Array 实例时, Array.isArray 优于 instanceof,因为 Array.isArray 能检测 iframes.

    var iframe = document.createElement('iframe')
    document.body.appendChild(iframe)
    xArray = window.frames[window.frames.length - 1].Array
    var arr = new xArray(1, 2, 3) // [1,2,3]
    
    // Correctly checking for Array
    Array.isArray(arr) // true
    // Considered harmful, because doesn't work though iframes
    arr instanceof Array // false
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    Array.isArray 是 ES2015 新增方法,假如不存在 Array.isArray(),可以用 Object.prototype.toString.call() 实现。

    if (!Array.isArray) {
      Array.isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]'
      }
    }
    
    1
    2
    3
    4
    5