toString方法和valueOf方法以及Symbol.toPrimitive方法的學習

valueOf()方法和toString()方法介紹

  • valueOf()方法和toString()

咱們知道在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()方法和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屬性。指向一個方法。該對象被轉化爲原始類型的值時,會調用這個辦法,返回該對象對應的原始類型值。
Symbol.toPrimitive被調用時,會接受一個字符串參數,表示當前運算的模式,一個有三種模式。

  • Number:該場合須要轉成數值
  • String:該場合須要轉成字符串
  • Default:該場合能夠轉成數值,也能夠轉成字符串。

以上內容來自阮老師的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、valueOf

固然,你也能夠重寫一個不作參數判斷的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...

相關文章
相關標籤/搜索