Object.prototype.toString.call()
const isArray = (arr)=>{
return Object.prototype.toString.call(arr) === "[object Array]"
}
const arr = [1,2,3,4];
const obj = {}
console.log(isArray(arr)) // true
console.log(isArray(obj)) // false
这样看起来没有问题,但是看一下下面的代码
const obj1 = {
[Symbol.toStringTag]: "Array"
}
console.log(isArray(obj1)) // true
因此,从上面的例子我们可以看出,对于大多数情况下,使用
Object.prototype.toString.call()
判断一个值是否为数组是有效的。但是,它可能存在一些问题和限制。
误判其他类似数组的对象:
Object.prototype.toString.call() 是根据对象的内部属性来判断类型。如果对象具有Symbol.toStringTag属性且内部值为Array,则无法正确判断对象是否为数组
instanceof
const isArray = (arr)=>{
return arr instanceof Array
}
const arr = [1,2,3,4]
const obj = {}
const obj1 = {
[Symbol.toStringTag]: "Array"
}
console.log(isArray(arr)) // true
console.log(isArray(obj)) // false
console.log(isArray(obj1)) // false
这种还会对继承类,也能准确判断出
class A extends Array {}
const arr1 = new A()
console.log(isArray(arr1)) // true
这样看起来似乎也没有什么题,但是看一下下面的代码
const obj2 = {};
Object.setPrototypeOf(obj, Array.prototype);
console.log(isArray(obj)); // true
因此,虽然
instanceof
在某些情况下可以用于判断值是否为真正的数组,但它也有局限性和误判的问题。
原型链的问题:
instanceof操作符会检查对象的原型链。因此,如果一个对象的原型链上的任何一个对象是Array.prototype,它也会被判断为数组
constructor
const isArray = (arr) => {
return arr.constructor === Array;
};
const arr = [1, 2, 3, 4];
const obj = {
[Symbol.toStringTag]: "Array",
};
const obj1 = {};
console.log(isArray(arr)); // true
console.log(isArray(obj)); // false
console.log(isArray(obj1)); // false
这样看起来似乎也没有什么问题,但是看一下下面的代码
class A extends Array {}
const arr1 = new A();
const arr2 = [];
arr2.constructor = Object;
const obj2 = {};
Object.setPrototypeOf(obj2, Array.prototype);
console.log(isArray(arr1)); // false
console.log(isArray(arr2)); // false
console.log(isArray(obj2)); // true
function CustomObject() {}
CustomObject.prototype = Object.create(Array.prototype);
const obj3 = new CustomObject();
console.log(isArray(obj3)); // true
从上面的例子可以看出,
constructor
在某些情况下可以用于判断值是否为真正的数组,但它也有局限性和误判的问题。
对象的constructor属性可以被修改:
constructor属性是一个指向创建对象的构造函数的引用。然而,它可以被修改,因此不能保证constructor属性的准确性对象原型链上的constructor属性可以被修改:
继承自数组原型链上的对象也会具有constructor属性,这可能导致误判
Array.isArray
const isArray = (arr)=>{
return Array.isArray(arr)
}
const arr = [1,2,3,4];
class A extends Array {}
const arr1 = new A()
const obj = {}
Object.setPrototypeOf(obj,Array.prototype)
const obj2 = {
[Symbol.toStringTag]: "Array"
}
console.log(isArray(arr)) // true
console.log(isArray(arr1)) // true
console.log(isArray(obj)) // false
console.log(isArray(obj2)) // false
Array.isArray()
是一个用于判断一个值是否为数组的内置方法,它通常是判断一个值是否为数组的首选方法
参考文档
本文只介绍js判断是否为数组的原生方法以及存在的问题,关于兼容性问题没有展开说明,有兴趣的可以查看上面的参考文档