判断一个变量的类型
typeof
通常使用 typeof a; 这样的方式也可以去判断一个变量的类型,但问题在于不严谨。比如:
typeof null; // object
typeof []; // object
但有时候,我们需要的是更‘纯粹’的对象,这个时候怎么办呢?
Object.prototype.toString.call(obj)
使用如标题那样的方式可以更好的区分各种变量的类型:
console.log(Object.prototype.toString.call("jerry"));//[object String]
console.log(Object.prototype.toString.call(12)); //[object Number]
console.log(Object.prototype.toString.call(true)); //[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null)); //[object Null]
console.log(Object.prototype.toString.call({name: "jerry"}));//[object Object]
console.log(Object.prototype.toString.call(function(){})); //[object Function]
console.log(Object.prototype.toString.call([])); //[object Array]
console.log(Object.prototype.toString.call(new Date)); //[object Date]
console.log(Object.prototype.toString.call(/\d/)); //[object RegExp]
美中不足的是,无法区分出自定义对象:
function Person(){};
console.log(Object.prototype.toString.call(new Person)); //[object Object]
但还有 instanceof
new Person() insatnceof Person; // true
为什么这样可以区分呢?
因为toStirng方法返回一个变量(包含对象)的字符串表示方式。那既然这样,为什么不直接使用obj.toString呢 ?
obj.toString
console.log("jerry".toString()); //jerry
console.log((1).toString()); //1
console.log([1,2].toString()); //1,2
console.log(new Date().toString());//Wed Dec 21 2016 20:35:48 GMT+0800 (中国标准时间)
console.log(function(){}.toString());//function (){}
console.log(null.toString()); //error
console.log(undefined.toString()); //error
同样是检测变量类型的方法,Object.prototype.toString.call(obj) 与 obj.toStirng 怎么会结果不一样呢?
这是因为toString方法是Objectde 原型方法,而 Array, function等类型作为Object的实例(Function是Object的子类,function又是Function的实例),都继承并重写了toString方法,不同的对象类型的对象调用toStirng方法时,其实调用的是重回写之后的toString方法,而不再去调用Object原型上的toString方法了。
我们可以验证一下,将数组的toString方法删除,看看会是什么结果:
var arr=[1,2,3];
console.log(Array.prototype.hasOwnProperty("toString")); //true
console.log(arr.toString()); //1,2,3
delete Array.prototype.toString; //delete操作符可以删除实例属性
console.log(Array.prototype.hasOwnProperty("toString")); //false
console.log(arr.toString()); //"[object Array]"
删除了Array的toString方法后,同样再采用arr.toString()方法调用时,不再有屏蔽Object原型方法的实例方法,因此沿着原型链,arr最后调用了Object的toString方法,返回了和Object.prototype.toString.call(arr)相同的结果。
另外,不直接使用obj.toString方法的原因,还有一个就是obj对象的toString方法有可能会被改写。