咱們知道在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...