美文网首页
JavaScript中的toString()和valueOf()

JavaScript中的toString()和valueOf()

作者: hjwang1024 | 来源:发表于2020-04-02 17:37 被阅读0次

    两者的关系

    • javaScript中toString()函数和valueOf函数是Object对象生来就拥有的(undefined和null没有toString()和valueOf()方法),并且他们还可以允许我们重写。
    • 举个栗子
    var arr = [1,2,3];  
    alert(Array.isArray(arr.valueOf()));  
    alert(Array.isArray(arr.toString()));  
    

    结果是第一个是true而第二个是false,原因是valueOf()调用完以后还是返回一个数组,这个数组被alert的时候会调用toString()函数;所以不是valueOf()和toString()函数相同,而是alert时间接调用了toString()函数!

    对象向基本数据类型的转换的规则

    1.vauleOf优先于toString()被调用---------当对象作为操作数的时候(Date类型的除外)
    var x="10";
    var a=+x;
    console.log(typeof a);     //number
    var b=a+x;
    console.log(typeof b);    //string
    var object={};
    object[a]=10000;
    console.log(object[10]);  //10000
    
    • "+"号作为一元运算符---- 在这个运算符下,对象向基本数据类型的转换规则:
      (1).当操作数是基本数据类型的时候,调用Number()函数,将其转换为数值
      (2). 当操作数是对象的时候,调用对象的toString或者valueOf函数,将对象转化为基本数据类型的值,然后再对该值调用Number()函数。
      所以,根据以上的转换规则,上述的输出结果为 number 也就合理了.
    • 但是,第二条转换规则里,蕴含了一个好大的坑啊:到底是调用toString()还是valueOf(),要是两个函数都能将对象转换为基本数据类型呢(比如Date类型的对象),你又调用谁呢?
    • 类似这样
    var x = {
      toString: function () {
        return '0';
      },
      valueOf: function () {
        return 1;
      }
    }
    var a = + x;  //到底调用的是toString()还是valueOf()呢?,在 + 号作为二元运算符的部分,会给出解释
    console.log(a);
    
    • “+”号作为二元运算符 ----- 在这个运算符下,对象向基本数据类型的转换规则:
      当“+”号作为二元运算符的时候情况就比较复杂了,因为"+"号可以当做字符串的连接,也可以当做数字的相加减。大约有以下规律:
    //伪代码,
    a + b运算转换规则:
    var Pa = toPrimitive(a);
    var pb = toPrimitive(b);
    if ((Pa is String) || (Pb is String)) {
      return contact(a, b)
    }
    if ((Pa is Number) && (Pb is Number)) {
      return a+b;
    }
     throw error;
     //注: toPrimitive 是将操作数转化为基本数据类型,优先调用valueOf,若得到基本数据类型,则结束,否则继续掉用toString()。(也就是说valueOf的优先级高于toString())
    
    • 即:含有字符串就是拼接,全为数字则为加法
    • +号作为一元运算符转换规则其实和其作为二元运算符差不多,转化为基本数据类型的时候总是优先调用valueOf()。
    var test = {
       valueOf: function () {
         return 1;
        },
       toString: function () {
         return '0';
        }
    }
    console.log( + test);   //1
    var result = test + test;
    console.log(result);  //2
    
    • 在操作数运算的时候(无论是一元的还是二元的运算),数据类型之间的转换总是优先调用valueOf()函数,但是“+”号在作为二元运算符时,这种优先顺序在应用于Date类型的对象时,被逆转了(toString的优先级较高)。
    • 谨记:Date类型是一个特例,当且仅当在+号运算,且“+”号作为二元运算符时,toString()优先调用,比如下面这样
    var date=new Date();
    console.log(+date);  //仍然优先调用valueOf  
    console.log(date+"toString优先被调用");
    //输出结果:
    // 1421293488713
    //Thu Jan 15 2015 11:44:48 GMT+0800toString优先被调用
    

    toString()优先于valueOf()被调用 ------当你想要输出结果是字符串的时候

    • 当访问Object类型对象的变量,我们用[] 这种方括号访问的时候,方括号的内容总是优先转化为字符串,也就是优先调用 toString()函数。
     1   var test = {
     2   toString: function () {
     3     return '0'
     4   },
     5   valueOf: function () {
     6     return 1;
     7   }
     8 };
     9 
    10 var object={};
    11 object[test]=1000;
    12 console.log(object);  // 输出结果:Object { 0=1000}
    
    
    [a]以这种形式访问的时候:
    var Pa=toPrimitive(a);
      if(Pa is prmitive){
        var str=String(Pa);
        }else{
            throw error;//cannot convert to string
        }
    [str]//str为字符串的形式
    //注: toPrimitive()此时优先调用toString()函数,若结果为基本类型,返回,否则继续调用valueOf(); 
    
    • 由上面可以看出,toString和valueOf这两个函数在转换的时候都是可能被调用的,只是在不同的环境下,调用的优先级不一样而已。这些对于我们程序员来说,可能是透明的,但是对于解释器说,它们干的活可就多了...一句话归结:解释器总是根据语境尽可能的转化为我们想要的结果。换句话说:
        对象在作为操作数时,解释器总是优先调用valueOf()--(Date类型的对象在二元“+”运算时例外),而其他情况,解释器总是认为我们想要的是字符串,所以会优先调用toString()..
      注:Date类型的对象之所以会在二元+运算时优先调用toString(),也是因为我们大多数情况下, 时间总是和字符串连接使用,而时间和一个数字相加的情况好少,所以Date类型中,toString()优先级才比较高。
      正是因为解释器总想完美的输出我们想要的结果,才会造成这种杂乱的现象和规则出现。天下间本没有完美的事物,矛和盾总是相依相存。
      懂得规则,才能利用规则,回过头来看一下我们在最开始所出的题目吧。是不是就是对这些规则的合理利用呢。
      题外话: 写这篇文章就是为了表明基础知识的重要性,并非追求一个稀奇古怪的程序,程序员追求的应该是通俗易懂的代码(大道至简)而不是这些看起来四不像的程序,切记本末倒置!

    备注: toLocaleString()这个函数是实现字符串的本地化的输出,一般和toString()输出的结果相同,没什么特殊的,就是一个普通的函数。在Date类型中,这个函数被重写了

    转自:https://blog.csdn.net/shaofei63/article/details/42743245

    相关文章

      网友评论

          本文标题:JavaScript中的toString()和valueOf()

          本文链接:https://www.haomeiwen.com/subject/ljaxphtx.html