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要领的返回值

对象返回值
Array返回数组对象自身
Boolean布尔值
Date返回的时刻是从1970年1月1日半夜最先计的毫秒数UTC
Function函数自身
Number数字值
Object对象自身。这是默许状况
String字符串值
Math和Error对象没有valueOf要领
  • 两者的运用场景以及区分与比较

经由过程来自MDN[!https://developer.mozilla.org…]上面临两个要领的引见,我们得知。这两个要领都是Object原型链上的要领,被每一个对象所继续。下面,我们看下该要领在两个运用场景下的区分。
1、关于值范例数据(又叫基础范例)场景下,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

toString放关于值范例数据运用而言,其效果相当于范例转换,将原范例转为字符串。

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要领关于值范例数据运用而言,其效果将相当于返回原数据。
2、复合对象范例数据运用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

个中,第一个alert,我们能够看到挪用了toString要领,申明alert这里是须要一个字符串,如许我们能够推想,toString()要领平常不须要我们主动去显现的挪用,相符对象范例会在响应的场景中挪用合适的要领,返回恰当范例的值。
第二个,这里经由过程alert我们晓得这里依然是须要一个字符串的值,所以这里是+test挪用了toString要领。而关于test,挪用valueOf要领。在有运算操作符的状况下,valueOf的优先级要高一点。能够看一个例子。

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
===操作符不举行隐式转换,判全等的第一个步骤是推断范例,因为范例都不一样了,所以背面什么都不会挪用.
总结:
1、在举行强转字符串范例时将优先挪用toString要领,强转为数字时优先挪用valueOf。
2、在有运算操作符的状况下,valueOf的优先级高于toString。
这两个要领平常是交由js去隐式挪用,以满足差别的运算状况。
在数值运算里,会优先挪用valueOf(),如 a + b;
在字符串运算里,会优先挪用toString(),如alert(c).

  • 补充下toString()要领和String()要领的区分

toString()要领和String()要领都能够转换为字符串范例。
1、toString()能够将一切的数据都转换为字符串,然则要消除null和undefined

var str = false.toString();
console.log(str, typeof str);         //false, string

然则 null和undefined不能转换为字符串,null和undefined挪用toString()要领会报错

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

2、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…

    原文作者:luoqua
    原文地址: https://segmentfault.com/a/1190000016300245
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞