toString && valueOf && Symbol.toPrimitive 辨析
我們知道在js中,'一切皆為物件'。每個物件都有一個toString()
方法和valueOf
方法,其中toString()
方法返回一個表示該物件的字串,valueOf
方法返回該物件的原始值。
1、toString && valueOf 二者的使用場景以及區別與比較
- 對於值型別資料(又叫基本型別)場景下,toString及valueOf方法的使用
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 複製程式碼
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方法
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 複製程式碼
總結
1、 在進行字串強轉時候,優先呼叫toString()方法。在進行數值運算的時候,優先呼叫valueOf方法。 2、 再有運算子的情況下,valueOf的優先順序要高於toString()方法。 複製程式碼
2、補充toString()和String()的區別
toString()方法和String()方法都可以轉換為字串型別。
(1)toString()
-
toString()可以將所有的資料都轉換為字串,但是要排除
null
和undefined
-
null和undefined不能轉換為字串,null和undefined呼叫toString()方法會報錯
-
如果當前資料為數字型別,則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 複製程式碼
(2)String()
- String()可以將null和undefined轉換為字串,但是沒法轉進位制字串。
3、Symbol.toPrimitive
物件的Symbol.toPrimitive
屬性。指向一個方法。該物件被轉化為原始型別的值時,會呼叫這個辦法,返回該物件對應的原始型別值。Symbol.toPrimitive
被呼叫時,會接受一個字串引數,表示當前運算的模式,一個有三種模式。
- Number:該場合需要轉成數值
- String:該場合需要轉成字串
- Default:該場合可以轉成數值,也可以轉成字串。
// 擁有 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); // Default 場景 3default console.log(obj + "");// Default場景 default console.log(String(obj)); //String場景 str 複製程式碼
由以上例子可以總結,一般情況下,+連線運算子傳入的引數是default,而對於乘法等算數運算子傳入的是number。對於String(str),${str}等情況,傳入的引數是defalut。
再者,Symbol.toPrimitive在型別轉換方面,優先順序是最高的。
let ab = { valueOf() { return 0; }, toString() { return '1'; }, [Symbol.toPrimitive]() { return 2; } } console.log(1+ab); // 3 console.log('1'+ab); // 12 複製程式碼