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()可以将所有的数据都转换为字符串,但是要排除nullundefined

  • 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


作者:meils
链接:https://juejin.im/post/5ca8074951882543be3ed16b
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值