面试那些事

Object.prototype.toString.call()

2022-09-25  本文已影响0人  _静夜听雨_

今天在网上遨游的时候,看到一个关于Object.prototype.toString.call()的面试题:
实现一个函数clone,可以对js中的5种主要的数据类型(包括number string object array Boolean)进行值复制
乍一看,这跟题目有啥关系,认真思考一下,发现其实就是在考察Object.prototype.toString.call()方法的使用。

JavaScript 里使用 typeof 来判断数据类型,只能区分基本类型,即 “number”,”string”,”undefined”,”boolean”,”object” 五种。对于数组、函数、对象来说,其关系复杂,若使用 typeof 都会统一返回 为object,这样为后续处理带来不便。关键函数方法 js原生方法Object.prototype.toString.call(),它可以给出数据的确切类型,相比typeof要精确。

回顾一下Object.prototype.toString.call使用

//1.判断基本类型:
 Object.prototype.toString.call(null);//”[object Null]”
 Object.prototype.toString.call(undefined);//”[object Undefined]”
 Object.prototype.toString.call(“abc”);//”[object String]”
 Object.prototype.toString.call(123);//”[object Number]”
 Object.prototype.toString.call(true);//”[object Boolean]”
 
//2.判断原生引用类型:
 //函数类型
  Function fn(){console.log(“test”);}
  Object.prototype.toString.call(fn);//”[object Function]”
 //日期类型
  var date = new Date();
  Object.prototype.toString.call(date);//”[object Date]”
// 数组类型
  var arr = [1,2,3];
  Object.prototype.toString.call(arr);//”[object Array]”
 //正则表达式
  var reg = /[hbc]at/gi;
  Object.prototype.toString.call(arr);//”[object Array]”
 //自定义类型
  function Person(name, age) {
      this.name = name;
      this.age = age;
  }
  var person = new Person("Rose", 18);
  Object.prototype.toString.call(arr); //”[object Object]”
 //很明显这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示:
 console.log(person instanceof Person);//输出结果为true
 
//3.判断原生JSON对象:                                                                                            
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
console.log(isNativeJSON);
//输出结果为”[object JSON]”说明JSON是原生的,否则不是;
//注意:Object.prototype.toString()本身是允许被修改的,而我们目前所讨论的
//关于Object.prototype.toString()这个方法的应用都是假设toString()方法未被修改为前提的。 

为什么不直接使用toString方法呢?查一下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

var a=new Number(12);
var toString=Object.prototype.toString;
console.log(toString.call(a)); //'[object Number]''
console.log(a.toString()); //'12'

因为toString为Object的原型方法,而Array,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串......),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转化为字符串类型;因此,在想要得到对象的具体类型时,应该调用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)相同的结果。

下面我们就可以来实现面试题复制函数了,代码如下:

function getDataType(data){  
    var getType=Object.prototype.toString;  
    var myType=getType.call(data);//调用call方法判断类型,结果返回形如[object Function]  
    var typeName=myType.slice(8,-1);//[object Function],即取除了“[object ”的字符串。  
    var copyData='';//复制后的数据  
    //console.log(data+" is "+myType);  
    switch(typeName){  
        case 'Number': copyData=data-0;  
                break;  
        case 'String': copyData="'"+data+"'";  
                break;  
        case 'Function': copyData=data;  
                break;  
        case 'Null': copyData=null;  
                break;  
        case 'Undefined': copyData="Undefined";  
                break;  
        case 'Array':   
                    copyData=[];//先将copyData变为空数组  
                    for(var i=0;i<data.length;i++){  
                        copyData[i]=data[i];//将data数组数据逐个写入copyData  
                    }  
                break;  
        case 'Object':   
                    copyData={};//先将copyData变为空对象  
                    for(var x in data){  
                        copyData[x]=data[x];  
                    }  
                break;  
        case 'Boolean': copyData=data;  
                break;  
        default : copyData=data;  
                break;  
    }  
    return copyData;  
}   
console.log(getDataType(123));  
console.log(getDataType("123"));  
console.log(getDataType(null));  
console.log(getDataType(undefined));  
console.log(getDataType(false));  
console.log(getDataType([1,2,4]));  
console.log(getDataType({"name":"wc"}));  
console.log(getDataType(function(){alert(23);}));

运行结果:


image.png

看完这个文章后,我相信你已经掌握了Object.prototype.toString.call()!!!

上一篇下一篇

猜你喜欢

热点阅读