Object.prototype.toString.call(obj) 与 obj.toString

判断一个变量的类型

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方法有可能会被改写。

    原文作者:李小叔
    原文地址: https://segmentfault.com/a/1190000011666656
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞