1、typeof操作符

typeof对于数组,返回的值永远是”object”,无法具体判断到底是数组还是对象

Type Result
Undefined "undefined"
Null "object" (see below)
Boolean "boolean"
Number "number"
String "string"
Symbol (new in ECMAScript 2015) "symbol"
Host object (provided by the JS environment) Implementation-dependent
Function object (implements [[Call]] in ECMA-262 terms) "function"
Any other object "object"

2、instanceof操作符

instanceof 操作符用来检测constructor.prototype是否存在于参数object的原型链上(换句话说,检测的是某个对象是否是某个类的实例)。

1
2
3
4
5
6
7
function D(){};
function C(){};

var o = new C();
o instanceof C;//true,因为Object.getPrototypeOf(o) === C.prototype

o instanceof D;//false, 因为D.prototype不在o的原型链上

使用instanceof判断是否是数组是有风险的,因为,对象的原型链我们可以手动更改。

1
2
o.__proto__ = D.prototype
o instance D;//true,因为D.prototype出现在了o的原型链上

所以使用instanceof判断一个对象是不是数组不可靠

3、原型链方法

1
2
3
var arr = [1,23,4];
arr.constructor == Array;//true
arr.__proto__.constructor == Array;//true

但是,这种方法也不可靠,因为对象的构造函数以及原型对象的构造函数都可以手动修改。

1
2
3
4
5
6
7
8
var obj = {};
obj.constructor = Array;
obj.__proto__.constructor = Array;
/*
obj不是一个数组,但是可以将其都构造函数手动改成Array
*/
obj.constructor == Array;//true
obj.__proto__.constructor == Array;//true

上面代码就说明,通过原型链来判断一个对象是不是数组,不可靠!

4、判断数组最准确的方法是使用Object.prototype.toString.call()

Object.prototype.toString()方法能够打印出对象的内置类型,并且,这个内置类型在对象创建之初就设定了,而且不可修改。

1
2
var arr = [];
Object.prototype.toString.call(arr) === "[object Array]";//true