判断数组(判断类型)

instanceof

instanceof 的内部机制是通过判断对象的原型链中是不是能找到类型的 prototype,意思就是判断对象是否是某一数据类型(如 Array)的实例,请重点关注一下是判断一个对象是否是数据类型的实例。 来看一个例子:

1
2
3
4
5
6
123 instanceof Number   // false
true instanceof Boolean    // false
'str' instanceof String    // false
[] instanceof Array    // true
function(){} instanceof Function  // true
{} instanceof Object   // true

结果显示,只有引用类型数据Array、Function、Object被准确判断,因为123、true、'str'是字面量,不是实例,所以判断为 false,实例化:

1
2
3
new Number(123) instanceof Number; //true
new Boolean(true) instanceof Boolean; // true
new String("str") instanceof String; // true
  • 需要注意的是,所有对象类型 instanceof Object都是 true

Array.isArray()

用来判断对象是否为数组 当检测Array实例时,Array.isArray 优于 instanceof ,因为 Array.isArray 可以检测出 iframes

1
2
3
4
5
6
7
8
9
10
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length - 1].Array;
var arr = new xArray(1, 2, 3); // [1,2,3]

// Correctly checking for Array
Array.isArray(arr); // true
Object.prototype.toString.call(arr); // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false

Object.prototye.toString.call()

每一个继承 Object 的对象都有 toString 方法,如果 toString 方法没有重写的话,会返回 [Object type],其中 type 为对象的类型。但当除了 Object 类型的对象外,其他类型直接使用 toString 方法时,会直接返回都是内容的字符串,所以我们需要使用 call 或者 apply 方法来改变 toString 方法的执行上下文。

1
2
3
4
5
6
7
Object.prototype.toString.call("An"); // "[object String]"
Object.prototype.toString.call(1); // "[object Number]"
Object.prototype.toString.call(Symbol(1)); // "[object Symbol]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(function() {}); // "[object Function]"
Object.prototype.toString.call({ name: "An" }); // "[object Object]"

Object.prototype.toString.call() 常用于判断浏览器内置对象时。 不过在 es6 中有方法能够修改

1
2
3
4
Object.prototype[Symbol.toStringTag] = "hello";

var a = {};
Object.prototype.toString.call(a); // [object hello]

typeof

1
2
3
4
5
6
7
8
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof "str"); // string
console.log(typeof []); // object     []数组的数据类型在 typeof 中被解释为 object
console.log(typeof function() {}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object     null 的数据类型被 typeof 解释为 object

constructor

1
2
3
4
5
6
console.log((2).constructor === Number); // true
console.log(true.constructor === Boolean); // true
console.log("str".constructor === String); // true
console.log([].constructor === Array); // true
console.log(function() {}.constructor === Function); // true
console.log({}.constructor === Object); //true

用 constructor 看似十分完美,然而只要更改对象的原型,这种方式就不可靠了

1
2
3
4
5
6
function Fn() {}
Fn.prototype = new Number();
var f = new Fn();
console.log(f.constructor === Fn); // false
console.log(f.constructor === Function); // false
console.log(f.constructor === Number); // true