今天分享一个平时经常用到但是不太注意的一个问题,那就是在js中如何判断一个东西是不是数组。
这个问题听起来好像挺简单的,但是能够很好的回答出来也是不简单的,我们一起来看一下。
以前常用的一种方法是使用…call(目标对象)来通过返回结果判断是不是数组,我们看如下代码:
const arr = [1, 2, 3, 4, 5]
const obj = { a: 1, b: 2 }
console.log(Object.prototype.toString.call(arr)) // [object Array]
console.log(Object.prototype.toString.call(obj)) // [object Object]
可以看到数组和对象返回结果通过第二个字符串就可以区分出来。
然后这种方法只适用于以前,这个以前指的是ES6引入一种新的原始数据类型以前,因为它有一个属性.可以对..方法返回的字符串进行修改,这里引用阮一峰大神在第三版ES6标注入门中的解释:
对象的.属性,用来设定一个字符串(设为其他类型的值无效,但不报错)。在目标对象上面调用..()方法时,如果.属性存在,该属性设定的字符串会出现在()方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[ ]或[ Array]中后面的那个大写字符串。
意思就是我们可以通过以下代码将对象类型的数据也修改成[ Array]返回结果:
const obj = {
[Symbol.toStringTag]: 'Array',
a: 1,
b: 2
}
console.log(Object.prototype.toString.call(obj)) // [object Array]
所以以前这种很好用的方法现在也用不了了。
那么第二种方法就是通过属性来判断,它是判断一个对象的原型链上有没有array的原型,我们也通过代码来看一下:
const arr = [1, 2, 3, 4, 5]
const obj = {
a: 1,
b: 2
}
const obj1 = {
[Symbol.toStringTag]: 'Array',
a: 3,
b: 4
}
console.log(arr instanceof Array) // true
console.log(obj instanceof Array) // false
console.log(obj1 instanceof Array) // false
可以看到对于普通数组,对象和.修改的对象都能判断出来,但是它也有一些特殊情况:
const obj = {
a: 1,
b: 2
}
Object.setPrototypeOf(obj, Array.prototype)
console.log(obj instanceof Array) // true
第一种特殊情况就是通过.方法修改原型的话就会判断错误。
第二种特殊情况就是如果在有标签的页面中,因为内部会有一套独立的和,就会造成不同环境下虽然都是同一个Array构造函数,但是值不一样,所以就会造成判断错误。
最后一种方法就是通过Array构造函数上的静态方法来判断,这个方法的描述mdn上是这样说明的:
Array.() 检查传递的值是否为 Array。它不检查值的原型链,也不依赖于它所附加的 Array 构造函数。对于使用数组字面量语法或 Array 构造函数创建的任何值,它都会返回 true。这使得它可以安全地使用跨领域(cross-realm)对象,其中 Array 构造函数的标识是不同的,因此会导致 Array 失败。
经过测试,以上遇到的特殊情况也都能够准确的判断出来,大家可以自行测试一下。
———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666