每日一题:如何判断是否是数组,一个既简单又复杂的问题。(不要再用Object.prototype.toString.call、instance of判断了!!!)

1、不要使用Object.prototype.toString.call()

正常情况下:

javascript 复制代码
const arr = [1,2,3,4,5]
const obj = {}
console.log(Object.prototype.toString.call(arr))//[Object,Array]
console.log(Object.prototype.toString.call(obj))//[Object,Object]

过去我们能够通过判断Object.prototype.toString.call(arr)第二个单词是否为Array来判断是否为数组,

但是时代变了,现在不行了。因为现在可以使用一个知名符号 toStringTag 改变生成的数组

例如:

javascript 复制代码
const arr = [1,2,3,4,5]
const obj = {
    [Symbol.toStringTag]:'Array',
}
console.log(Object.prototype.toString.call(arr))//[Object,Array]
console.log(Object.prototype.toString.call(obj))//[Object,Array]

看到了吗?对象用这个方法,也可以把第二个单子变成Array。

虽然概率很小,但是不得不防。还是那句话你可以不用,但是你不能知道!!!

2、不要使用instance of

原理是通过判断一个对象上有没有Array的原型

正常情况下:

javascript 复制代码
const arr = [1,2,3,4]
const obj = {}
console.log(arr instanceof Array) //true
console.log(obj instanceof Array) //false

说完正常情况下,就说一说不正常的情况下

  1. 通过Object.setPrototypeOf 将对象的原型改变为数组的原型
javascript 复制代码
const arr = [1,2,3,4]
const obj = {}
Object.setPrototypeOf(obj,Array.prototype)
console.log(arr instanceof Array) //true
console.log(obj instanceof Array) //true

将对象也判断成数组了 ,哒咩

  1. 在页面环境中有iframe
    由于iframe会生成一套独立的document和独立的window,但是Array是window一个全局属性,这就造成了一个非常有意思的现象
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<iframe src="" frameborder="0"></iframe>
</body>
<script>
    const Array1 = window.Array
    const iframe = document.querySelector('iframe')
    const Array2 = iframe.contentWindow.Array
    const arr = new Array2()
    console.log(arr instanceof Array) //false
</script>
</html>

虽然我觉得出现这种情况的概率很小,但是还是那句话你可以不用,但是你不能知道!!!

3、唯一解:Array.isArray

javascript 复制代码
const arr = [1,2,3,4,5]
//上述两种情况均可用Array.isArray判断
Array.isArray(arr) //true