toSring方法的调用

387 阅读4分钟

toString来源

Object类型的每个实例都有toString()方法,返回对象的字符串表示 '[object,Object]',所以每个实例化对象都可以调用toString方法.

顺着实例化对象原型链obj=>obj._proto_=>Object.prototype知道 toString方法是定义在Object.prototype上的

  • 然而不同类型都或多或少的重写了toString()方法 ,因此不同类型调用toString()方法会产生的值各不相同

不同对象toString方法的返回

对象Object

对象类型的调用toString方法都会返回对象的字符串表示

  • 下面是一种常见的判断类型的方法 任何对象都可以通过this绑定调用Object.prototype.toString()方法 返回对象的字符串表示
Object.prototype.toString.call({});
<!--"[object Object]"-->

Object.prototype.toString.call([]);
<!--"[object Array]"-->

Object.prototype.toString.call(function(){});
<!--"[object Function]"-->

Object.prototype.toString.call('');
<!--"[object String]"-->

Object.prototype.toString.call(1);
<!--"[object Number]"-->

Object.prototype.toString.call(true);
<!--"[object Boolean]"-->

Object.prototype.toString.call(null);
<!--"[object Null]"-->

Object.prototype.toString.call(undefined);
<!--"[object Undefined]"-->

Object.prototype.toString.call();
<!--"[object Undefined]"-->

Object.prototype.toString.call(new Date());
<!--"[object Date]"-->

Object.prototype.toString.call(/at/);
<!--"[object RegExp]"-->

数组Array

返回由数组中每个值的字符串形式拼接而成的以逗号分隔的一个字符串

var array = [1, 's', true, {a: 2}];
array.toString();//"1,s,true,[object Object]"
Array.prototype.toString.call(array);//"1,s,true,[object Object]"

  • 以上可以看出 数组对象可以通过this绑定调用Array.prototype.toString()方法,返回数组值的字符串拼接
Array.prototype.toString.call({});
<!--"[object Object]"-->
Array.prototype.toString.call(function(){})
<!--"[object Function]"-->
Array.prototype.toString.call(1)
<!--"[object Number]"-->
Array.prototype.toString.call('')
<!--"[object String]"-->
Array.prototype.toString.call(true)
<!--"[object Boolean]"-->
Array.prototype.toString.call(/s/)
<!--"[object RegExp]"-->

Array.prototype.toString.call();
<!--Cannot convert undefined or null to object at toString-->
Array.prototype.toString.call(undefined);
Array.prototype.toString.call(null);

  • 但是非数组对象通过this绑定调用Array.prototype.toString方法,返回的是该对象的字符串表示。
  • 另外null和undefined不可以通过绑定调用Array.prototype.toString方法

函数Function

toString():返回函数的代码

function foo(){
    console.log('function');
};
foo.toString();
<!--"function foo(){-->
<!--    console.log('function');-->
<!--}"-->


Function.prototype.toString.call(foo);
<!--"function foo(){-->
<!--    console.log('function');-->
<!--}"-->

注意

Object.toString();
//"function Object() { [native code] }"
Function.toString();
//"function Function() { [native code] }"
Array.toString();
//"function Array() { [native code] }"
....

  • 以上构造函数的toString方法都是返回的函数代码
Function.prototype.toString.call({});
<!--Function.prototype.toString requires that 'this' be a Function-->

  • 非函数对象不能通过绑定this来调用原型方法

日期Date

返回带有时区信息的日期和时间

var date = new Date();
date.toString();
//"Fri Mar 05 2020 16:53:43 GMT+0800 (中国标准时间)"
Date.prototype.toString.call(date);
//"Fri Mar 05 2020 16:53:43 GMT+0800 (中国标准时间)"

正则表达式RegExp

返回正则表达式的字面量

var reg = /cat/g;
reg.toString();// "/cat/g"
RegExp.prototype.toString.call(re);// "/cat/g"

基本包装类型

什么是基本包装类型((Boolean、Number、String))

var str = 'beatrix';
str.toString();//"beatrix"

str不是一个基本类型吗,怎么可以调用toString方法呢?

  • str 和strObject 的区别
var str = 'I am a string';
typeof str; //"string"
str instanceof String; //false

var strObject = new String('I am a string');
typeof strObject; //"object"
strObject instanceof String; //true
strObject instanceof Object; //true

  • 由于String基本包装类型的存在,在必要的时候JS引擎会把字符串字面量转换成一个String对象 过程:

创建一个String类型的实例--->在这个实例上调用指定的方法--->销毁这个实例

var strObject = new String('beatrix');
strObject.toString(); //'beatrix'
strObject = null;

字符串 String

返回字符串的一个副本

var str = "a";
str.toString(); //"a"
String.prototype.toString.call(str); //"a"

数值Number

返回字符串形式的数值

var num = 520;
num.toString(); //"520"
Number.prototype.toString.call(num); //"520"

布尔值Boolean

返回字符串形式的数值

var boo = true;
boo.toString(); //"true"
Boolean.prototype.toString.call(boo); //"true"

undefined和null

null和undefined没有相应的构造函数,所以它们没有也无法调用toString()方法,也就是说它们不能访问任何属性和方法,只是基本类型而已。

全局对象window

Object、Array、Function都是window对象的属性。

返回对象的字符串表示

window.toString();
<!--"[object Window]"-->
Window.prototype.toString.call(window);//这里其实有问题
<!--"[object Window]"-->

  • Winodw类并没有在Window.prototype原型对象上重写toString()方法,它会顺着原型链查找调用Object.prototype.toString()。
  • 所以,任何对象object都可以通过this绑定调用Window.prototype.toString()方法,也就是调用Object.prototype.toString()方法,结果和Object是一样。

直接调用toString

toString();
<!--"[object Undefined]"-->

(function(){
    console.log(toString());
})();
<!--[object Undefined]-->

直接调用等价于

Object.prototype.toString.call();
<!--"[object Undefined]"-->
Object.prototype.toString.call(undefined);
<!--"[object Undefined]"-->

直接调用toString.call

toString.call({});
<!--"[object Object]"-->
toString.call([]);
<!--"[object Array]"-->

等价于Object.prototype.toString() 但是如果重写了toString方法就不会默认调用原型对象上的toString方法

总结

除了Object和Array两种情况,其他类型都不支持非自身实例通过this绑定调用该Object子类原型对象上的toString()方法,这说明在重写toString()方法时,明确限定了调用该方法的对象类型。

所以,一般我们只使用Object.prototype.toString.call/apply()方法来通过this绑定调用,判断其准确类型。