咱们知道在js中,'一切皆为对象'。每一个对象都有一个toString()方法和value方法,其中toString()方法返回一个表示该对象的字符串,value方法返回该对象的原始值。对于toString方法来讲,当对象被表示为文本值或者当以指望字符串的方式引用对象时。该方法被自动调用。对于一个对象,toSting()返回"[object type]",其中type是对象类型。若是x不是对象,toString()返回应有的文本值。
对于valueOf() 方法来讲,默认状况下, valueOf() 会被每一个对象Object继承。每个内置对象都会覆盖这个方法为了返回一个合理的值,若是对象没有原始值,valueOf() 就会返回对象自身。
可是注意,对于Null若是
不一样类型的对象的value方法的返回值html
对象 | 返回值 |
---|---|
Array | 返回数组对象自己 |
Boolean | 布尔值 |
Date | 返回的时间是从1970年1月1日午夜开始计的毫秒数UTC |
Function | 函数自己 |
Number | 数字值 |
Object | 对象自己。这是默认状况 |
String | 字符串值 |
Math和Error对象没有valueOf方法 |
经过来自MDN[!https://developer.mozilla.org...]上面对两个方法的介绍,咱们得知。这两个方法都是Object原型链上的方法,被每一个对象所继承。下面,咱们看下该方法在两个应用场景下的区别。
一、对于值类型数据(又叫基本类型)场景下,toString及valueOf方法的使用git
var str = "hello",n = 123,bool = true; console.log(typeof(str.toString())+ "_"+ str.toString()) //string_hello console.log(typeof(n.toString())+"_"+n.toString() ) //string_123 console.log(typeof(bool.toString())+"_"+bool.toString()) //string_true
toString放对于值类型数据使用而言,其效果至关于类型转换,将原类型转为字符串。es6
console.log(typeof(str.valueOf())+"_"+str.valueOf()) //string_hello console.log(typeof(n.valueOf())+"_"+n.valueOf()) //string_123 console.log(typeof(bool.valueOf())+"_"+bool.valueOf()) //string_true console.log(str.valueOf === str) // // true console.log(n.valueOf === n) // // true console.log(bool.valueOf() === bool) // true
由上面的例子能够得出,
toString方法对于值类型数据使用而言,其效果至关于类型转换,将原类型转为字符串。
valueOf方法对于值类型数据使用而言,其效果将至关于返回原数据。
二、复合对象类型数据使用toString及valueOf方法github
var obj = {}; console.log(obj.toString()); //[object Object] 返回对象类型 console.log(obj.valueOf()); //{} 返回对象自己
能够看到与方法介绍中所说一致。下面让咱们看下,具体两个方法是如何执行的。数组
var test = { i: 10, toString: function() { console.log('toString'); return this.i; }, valueOf: function() { console.log('valueOf'); return this.i; } } alert(test);// 10 toString alert(+test); // 10 valueOf alert(''+test); // 10 valueOf alert(String(test)); // 10 toString alert(Number(test)); // 10 valueOf alert(test == '10'); // true valueOf alert(test === '10'); // false
其中,第一个alert,咱们能够看到调用了toString方法,说明alert这里是须要一个字符串,这样咱们能够推测,toString()方法通常不须要咱们主动去显示的调用,符合对象类型会在相应的场景中调用适合的方法,返回适当类型的值。
第二个,这里经过alert咱们知道这里依然是须要一个字符串的值,因此这里是+test调用了toString方法。而对于test,调用valueOf方法。在有运算操做符的状况下,valueOf的优先级要高一点。能够看一个例子。frontend
var ab = { i: 1, valueOf: function () { alert("你调用了a的valueOf函数"); return this.i; }, toString: function () { alert("你调用了a的toString函数"); return this.i; } }; var c = { i: +ab, valueOf: function () { alert("你调用了c的valueOf函数"); return this.i; }, toString: function () { alert("你调用了c的toString函数"); return this.i; } }; alert(c);
第三个,一样咱们能够把上面的例子改成。函数
var c = { i: ''+ab, valueOf: function () { alert("你调用了c的valueOf函数"); return this.i; }, toString: function () { alert("你调用了c的toString函数"); return this.i; } }; alert(c);
第四个,String方法是要返回一个字符串类型,因此这里调用了toString()方法。
第五个,强转换为数字类型,调用了valueOf方法。
第六个,这个里面的判等的顺序是,获取原始值,而后判断两边的原始值是否相等,因此调用valueOf。
第七个,alert(bbb === '10'); // false
===操做符不进行隐式转换,判全等的第一个步骤是判断类型,由于类型都不同了,因此后面什么都不会调用.
总结:
一、在进行强转字符串类型时将优先调用toString方法,强转为数字时优先调用valueOf。
二、在有运算操做符的状况下,valueOf的优先级高于toString。
这两个方法通常是交由js去隐式调用,以知足不一样的运算状况。
在数值运算里,会优先调用valueOf(),如 a + b;
在字符串运算里,会优先调用toString(),如alert(c).this
toString()方法和String()方法均可以转换为字符串类型。
一、toString()能够将全部的数据都转换为字符串,可是要排除null和undefined.net
var str = false.toString(); console.log(str, typeof str); //false, string
可是 null和undefined不能转换为字符串,null和undefined调用toString()方法会报错3d
var str = null.toString(); var str = undefined.soString();
若是当前数据为数字类型,则toString()括号中的能够写一个数字,表明进制,能够将数字转化为对应进制字符串。
var num = 123; console.log(num.toString()+'_'+ typeof(num.toString())); //123_string console.log(num.toString(2)+'_'+typeof(num.toString())); //1111011_string console.log(num.toString(8)+'_'+typeof(num.toString())); //173_string console.log(num.toString(16)+'_'+typeof(num.toString())); //7b_string
二、String()能够将null和undefined转换为字符串,可是无法转进制字符串。当 String() 和运算符 new 一块儿做为构造函数使用时,它返回一个新建立的 String 对象,存放的是字符串 s 或 s 的字符串表示。
var str = new String("123"); console.log(str+"_"+typeof(str)); //123_object
当不用 new 运算符调用 String() 时,它只是把s转换成原始的字符串,并返回转换后的值。
var str = String(s); console.log(str+"_"+typeof(str)) //123_string
对象的Symbol.toPrimitive属性。指向一个方法。该对象被转化为原始类型的值时,会调用这个办法,返回该对象对应的原始类型值。
Symbol.toPrimitive被调用时,会接受一个字符串参数,表示当前运算的模式,一个有三种模式。
以上内容来自阮老师的ES6入门,下面咱们结合几个例子,具体看下Symbol.toPrimitive是如何被调用的。
// 没有 Symbol.toPrimitive 属性的对象 var obj1 = {}; console.log(+obj1); //NaN console.log(`${obj1}`); //"[object Object]" console.log(obj1 + ""); //"[object Object]"
上面的结果咱们能够经过上面说的toSting()方法和value方法去理解。
第一个,+符号。能够当作是是把数据转化为数字类型,因为obj是个空对象,因此结果是NaN
第二个,是es6中的字符串的新语法,这里须要的结果是一个字符串,因此使用的是toString()方法,而toString()方法返回的是对象的类型。
第三个,这里是链接符链接obj。实际上也是须要字符串的结果,因此同理。
// 拥有 Symbol.toPrimitive 属性的对象 var obj2 = { [Symbol.toPrimitive](hint) { if(hint == "number"){ return 10; } if(hint == "string"){ return "hello"; } return true; } } console.log(+obj2); //10 --hint in "number" console.log(`${obj2}`); //hello --hint is "string" console.log(obj2 + ""); //"true"
// 拥有 Symbol.toPrimitive 属性的对象 let obj = { [Symbol.toPrimitive](hint) { if(hint === 'number'){ console.log('Number场景'); return 123; } if(hint === 'string'){ console.log('String场景'); return 'str'; } if(hint === 'default'){ console.log('Default 场景'); return 'default'; } } } console.log(2*obj); // Number场景 246 console.log(3+obj); // String场景 3default console.log(obj + ""); // Default场景 default console.log(String(obj)); //String场景 str
由以上例子能够总结,通常状况下,+链接运算符传入的参数是default,而对于乘法等算数运算符传入的是number。对于String(str),${str}
等状况,传入的参数是defalut。
固然,你也能够重写一个不作参数判断的Symbol.toPrimitive方法,结合上面提到的toString,能够有如下例子。
let ab = { valueOf() { return 0; }, toString() { return '1'; }, [Symbol.toPrimitive]() { return 2; } } console.log(1+ab); console.log('1'+ab);
能够看到,Symbol.toPrimitive方法在转换基本类型的时候优先级最高。
参考连接:
http://www.sohu.com/a/1464105...
https://www.cnblogs.com/good1...
https://www.jb51.net/article/...
https://yuchengkai.cn/docs/zh...
https://github.com/ruanyf/es6...
https://developer.mozilla.org...
https://blog.csdn.net/kittyji...