从toString()方法到Object.prototype.toString.call()方法
时间:2022-05-05 17:57
一、toString方法和Object.prototype.toSting.call()的区别
var arr=[1,2];
直接对一个数组调用toString()方法,
console.log(arr.toString()); //输出1,2 现在通过call方法指定arr数组为Object.prototype对象中的toString方法的上下文。 console.log(Object.prototype.toString.call(arr)); //输出[Object Array] 错误理解:按照arr是Object对象的子集,应该toString()方法会继承下来,所以两个得到的结果应该是一样的,但是现实是残酷的。 原因:Object.prototype的toString方法确实被继承下来了,但是很多东西总不会一层不变,作为儿子的数组重写了toString方法,所以直接调用数组对象上面的toString方法调用到的实际是重写后的方法,并不是Object.prototype中的toString方法。Array,Function等类型作为Object的实例,都重写了toString方法,不同的对象类型调用toString()方法时,根据原型链的知识,调用的是重写之后的toString方法(函数返回的是函数体内的字符串,Array返回的是元素组成的字符串) 应用场景:Object.prototype对象上的toString方法可以用来判断数据类型 例如:Object.prototype.toString.call(arr); 输出:[Object Array] 判断是否是数组 例子2: var arr=[1,2,3]; console.log(Array.prototype hasOwnPrototype(‘toString‘)) //true console.log(arr.toString()) //1,2,3 delete Array.prototype.toString; //delete操作符可以删除实例属性 console.log(Array.prototype hasOwnPrototype(‘toString‘)) //false console.log(arr.toString()) //[object Array]; 删除了Array的toString方法后,同样采用arr.toString()方法调用,不再屏蔽Object原型方法的实例方法,arr最后调用了Object的toString方法。 而重写后的toString方法可以把对象转换成字符串,还可以把数值转换成不同进制的数字 [1,2].toString();//1,2 得到字符串 (10).toString(2) //十进制转二进制,输出1010,如果10.toString(2)会报错,因为js会认为.是数字的小数点而不是调用符号。 二、为什么用Object.prototype.toString.call(obj)检测对象类型? 第一种:用typeof判断 我们知道typeof可以检测数据类型,对变量或值调用typeof运算符将返回下列值之一: undefined->Undefined boolean->Boolean number->Number string->String object->是引用类型或null类型。 function->function函数 typeof检测引用类型或null是不能准确区分arr json等引用类型的。 那我们还知道一种检测方式instanceof,来检测某个对象是不是另一个对爱心那个的实例 第二种:用instanceof判断 instanceof运算符用来测试一个对象在其原型链中是否存在一个构造函数的prototype属性。 主要用来检测引用类型,判断Array和RegExp,无法准确判断Function. console.log([] instanceof Array) //true console.log({} instanceof Object) //true console.log(/\d/ instanceof RegExp) //true console.log(function(){} instanceof Object) //true console.log(function(){} instanceof Function) //true console.log(‘‘ instanceof String) //false console.log(1 instanceof Number) //false var a=new Array(); alert(a instanceof Array); 同时alert(a instanceof Object)也会返回true,因为Array是object的子类。 function test(){} var a=new test(); alert(a instanceof test);会返回true. alert(a==b) //false; 另外,更重要的一点是instanceof可以在继承关系中用来判断一个实例是否属于他的父类型。 function Foo(){} Foo.prototype=new Aoo() //js原型继承 var foo= new Foo(); console.log(foo instanceof Foo) //true console.log(foo.instanceof Aoo) //true 上面代码中是判断了一层继承关系的父类,在多层继承关系中,isntanceof运算符同样适用。 //定义构造函数 function C(){} function D(){} var o=new C(); o instanceof C //true o instanceof D //false 因为D.prototype不在o的原型链上 o instanceof Object //true 因为Object.prototype.isPrototypeOf(o) 返回true C.prototype instanceof Object //true 同上 C.prototype={} var o2=new C(); o2 instanceof C //true o instanceof C //false C。prototype指向了一个空对象,这个空对象不在o的原型链上。 D.prototype =new C(); //继承 var o3=new D(); o3 instanceof D //true o3 isntanceof C //true 谈到instanceof 我们要多插入一个问题,就是function的arguments,我们大家也许认为arguments是一个Array,但如果用instanceof去测试回发现arguments不是一个Array对象,尽管看起来很像。 第三种:Object.prototype.toString 这是对象的一个原生扩展函数,用来精确区分数据类型 var type=Object.prototype.toString console.log(type.call(‘‘)) //object String console.log(type.call([])) //object Array console.log(type.call({})) //object Object console.log(type.call(false)) //object Boolean console.log(type.call(null)) //object Null console.log(type.call(undefined)) //object Undefined console.log(type.call(function(){})) //object Function