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...

相关文章
相关标签/搜索