跳转到内容

判断是否是数组

刀刀

4/7/2025

0 字

0 分钟

判断是否是数组有以下几种方法:

  1. Object.prototype.toString
  2. instanceof
  3. isArray

Object.prototype.toString

下面来看一段代码:

js
let arr = [1, 2, 3]
let obj = {}
console.log(Object.prototype.toString.call(arr)) // [object Array]
console.log(Object.prototype.toString.call(obj)) // [object Object]

因此可以通过第二个单词是否是 Array 来判断该变量是否是数组。在过去可以写出以下代码来判断:

js
function isArray(arr) {
    return Object.prototype.toString.call(arr) === '[object Array]'
}

在以前这个方法是可以使用的,但是现在不可以了。在之前变量无法更改这个字符串,但是现在可以可以了,通过 toStringTag 来修改。代码如下:

js
let obj = {
    [Symbol.toStringTag]: 'Array'
}

isArray(obj) // true

因此这个方法现在无法百分百保证正确了。

instanceof

instanceof 能判断一个变量的原型链条上有没有 array 的原型,代码如下:

js
function isArray(arr) {
    return arr instanceof Array
}

let obj = {
    [Symbol.toStringTag]: 'Array'
}
isArray(obj) // false

class A extends Array {}
const a = new A()
isArray(a) // true

该方法也能正常运作,且不会受 toStringTag 的影响,继承也能够正常识别。

但是它还是有两个问题:

  1. 使用 setPrototypeOf 修改原型为数组原型会判断为 true
  2. iframe 是独立的,它有自己的 window 环境,如果使用 iframe 内的数组环境生成的变量,原型判断为 false

代码如下:

js
// setPrototypeOf
let obj = {}
Object.setPrototypeOf(obj, Array.prototype)
isArray(obj) // true

// iframe
let Array1 = window.Array
let iframe = document.querySelector('iframe')
let Array2 = iframe.contentWindow.Array
console.log(Array1 == Array2) // false
let arr = new Array2()
console.log(arr instanceof Array) // false。Array是当前环境的Array,不是iframe的Array,所以是false

isArray

数组是一个特殊的对象,底层源码会有一个特殊的存储结构,在浏览器控制台输入 Array 可以看到。

Array

所以需要一个方法判断该对象是否经过这些构造函数。isArray 方法判断的依据就是当前变量是否经过 native code 。下面来看一下代码:

js
let Array2 = iframe.contentWindow.Array
let arr = new Array2()
console.log(Array.isArray(arr)) // true

let obj = {}
Object.setPrototypeOf(obj, Array.prototype)
console.log(Array.isArray(obj)) // true