1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
      <output id="hzk7v"></output>
    2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
    3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

      JavaScript高阶教程之¡°==¡±隐藏下的类型转换

       更新时间£º2019年04月11日 10:54:57   作者£ºwuming   我要评论

      这篇文章主要给大家介绍了关于JavaScript高阶教程之¡°==¡±隐藏下类型转换的相关资料£¬文?#22411;?#36807;示例代码介绍的非常详细£¬对大家学习或者使用JavaScript具有一定的参考学习价值£¬需要的朋友们下面来一起学习学习吧

      抛砖引玉

      按照正常的逻辑来说£¬我们判断两个值是否相等会遵循以下规则£º


      但是我看下面一组值£º

      []==0 //true
      []==false //true
      []==!{} //true
      [10]==10 //true
      '0'==false //true
      ''==0 //true
      undefined==null //true 
      !null==true //true 

      居然没有按照我们的剧本走£¬那它比较规则?#36136;?#20160;么£¿下面我就来分析一波¡£

      ¡°==¡±的比较规则

      首先我们先去ECMAScript5.1中文版£¨ http://lzw.me/pages/ecmascrip... £©找一下¡°==¡±的比较规则£¬如下£º

      1.若Type(x)与Type(y)相同£¬ 则
          a.若Type(x)为Undefined£¬ 返回true¡£
          b.若Type(x)为Null£¬ 返回true¡£
          c.若Type(x)为Number£¬ 则
              i.若x为NaN£¬ 返回false¡£
              ii.若y为NaN£¬ 返回false¡£
              iii.若x与y为相等数值£¬ 返回true¡£
              iv.若x 为 +0 且 y为−0£¬ 返回true¡£
              v.若x 为 −0 且 y为+0£¬ 返回true¡£
              vi返回false¡£
          d.若Type(x)为String, 则当x和y为完全相同的字符序列£¨长度相等且相同字符在相同位置£©时返回true¡£ 否则£¬ 返回false¡£
          e.若Type(x)为Boolean, 当x和y为同为true或者同为false时返回true¡£ 否则£¬ 返回false¡£
          f.当x和y为引用同一对象时返回true¡£否则£¬返回false¡£
      2.若x为null且y为undefined£¬ 返回true¡£
      3.若x为undefined且y为null£¬ 返回true¡£
      4.若Type(x) 为 Number 且 Type(y)为String£¬ 返回comparison x == ToNumber(y)的结果¡£
      5.若Type(x) 为 String 且 Type(y)为Number£¬返回比较ToNumber(x) == y的结果¡£
      6.若Type(x)为Boolean£¬ 返回比较ToNumber(x) == y的结果¡£
      7.若Type(y)为Boolean£¬ 返回比较x == ToNumber(y)的结果¡£
      8.若Type(x)为String或Number£¬且Type(y)为Object£¬返回比较x == ToPrimitive(y)的结果¡£
      9.若Type(x)为Object且Type(y)为String或Number£¬ 返回比较ToPrimitive(x) == y的结果¡£
      10.返回 false

      看完ECMAScript5.1中文版的介绍之后£¬相信很多小伙伴的心情应该是这样的£º


      别看上面说的有点花里胡哨的£¬其实我们可以用很简单的话来总结出来¡£由于本篇文章核心是¡°==¡±是如何进行类型转换£¬我就总结一下类型不同的情况下¡°==¡±是如何比较的¡£

      • 当数据类型为Boolean类型或者String类型时£¬比较时需要转换成Number类型¡£
      • 当数据类型为引用类型时£¬需要转换成原始数据类型¡£当转换后的原始数据类型为Boolean类型或者String类型£¬则继续转换成Number类型¡£
      • undefined和null跟任何值在¡°==¡±下都返回false£¬但二者在¡°==¡±下返回true¡£

      具体流程图如下£º

      备注£º

      Javascript的数据类型可以分为以下两种:

      • 原始数据类型£¨null¡¢undefined¡¢Number¡¢String¡¢Boolean¡¢Symbol£¨Es6才引入的£©£©
      • 引用类型 (Object)

      Boolean类型¡¢String类型转换成Number类型的规则£¨ToNumber£©

      Boolean类型

      Boolean Number
      true 1
      false 0

       

      String类型

      标准的数字格式
      如果是标准的数字格式£¬转换成Number类型相比不用多说£¬比如下面这几个栗子🌰£º

      "123" => 123
      "12.34" => 12.34
      "0.12" => 0.12
      "-12.34" => -12.34

      非标准的数字格式

      但是如果是非标准的数据格式£¬要分两种情况来考虑£º

      • 第一种£º?#35805;?#21547;数字并且最多只有1个点¡£
      • 第二种£º包含非数字以及含有多个1个点¡£

      ?#35805;?#21547;数字并且最多只有1个点

      这种情况下会首先进行补0和去0的操作£¬下面看几个栗子🌰£º

      "01234" => 1234
      ".1" => 0.1
      "12." => 12
      "1.000" => 1
      "-02.30" => -2.3

      包含非数字以及含有多个1个点

      这种情况下统统返回NaN£¬意为¡°Not a Number¡±,这里我们要注意一下£¬NaN还是Number类型£¬下面看几个栗子🌰£º

      "123aa4" => NaN
      "哈喽£¬DD" => NaN
      typeof NaN => "numer"

      引用类型转换成原始数据类型的规则£¨ToPrimitive£©

      在介绍转换规则之前£¬首先我们我们介绍一下引用类型都带有的两个方法£º

      • Object.prototype.toString
      • Object.prototype.valueOf

      这二者都可以将引用类型转换成原始数据类型£¬接下来我们对二者做一个详细的介绍£º

      Object.prototype.toString

      MDN是这样解释的£º

      The toString() method returns a string representing the object.£¨toString()这个方法返回一个代表这个对象的字符串£©

      举个栗子🌰£º

      const obj = {}
      console.log(String(obj)) //"[object Object]"
      obj.toString = function(){
       return 'Hello,Teacher Cang!'
      }
      console.log(String(obj)) //"Hello,Teacher Cang!"

      Object.prototype.valueOf

      MDN是这样解释的£º

      The valueOf() method returns the primitive value of the specified object.£¨ valueOf()这个方法返回这个对象的原始数据值£©

      举个栗子🌰£º

      const obj = {}
      console.log(Number(obj)) //NaN
      obj.valueOf = function(){
       return 12345;
      }
      console.log(Number(obj)) //12345

      valueOf和toString的优先级

      关于这二者的优先级£¬在不同的情况下有着不同的优先级£¬下面我们根据不同情况介绍一下¡£

      ToNumber

      看个栗子🌰£º

      const obj = {
       toString(){
       console.log('调用了toString');
       return 'Hello,Teacher Cang!';
       },
       valueOf(){
       console.log('调用了valueOf');
       return 12345;
       }
      }
      console.log(Number(obj)); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了valueOf
      12345

      通过上面的代码的运行结果£¬我们得出这么一个结论£º

      在ToNumber情况下£¬valueOf的优先级大于toString¡£

      接下里我们看这么一种情况£¬如果valueOf返回的并不是原始数据类型会怎么样¡£

      const obj = {
       toString(){
       console.log('调用了toString');
       return 12345;
       },
       valueOf(){
       console.log('调用了valueOf');
       return {};
       }
      }
      console.log(Number(obj)); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了valueOf
      调用了toString
      12345

      从上面的运行结果中£¬我们可以得出这么一个结论£º

      在ToNumber情况下£¬如果valueOf返回的不是原始数据类型£¬则会自动调用toString¡£

      打破砂锅?#23454;?#24213;£¬再来一个非常极端的情况£¬如果说valueOf和toString返回的都不是原始数据类型£¬这时又该怎么样呢?#23458;?#26679;£¬我们继续看一下运行结果£º

      const obj = {
       toString(){
        console.log('调用了toString');
        return {};
       },
       valueOf(){
        console.log('调用了valueOf');
        return {};
       }
      }
      console.log(Number(obj)); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了valueOf
      调用了toString
      Uncaught TypeError: Cannot convert object to primitive value

      从上面的运行结果中£¬我们再次可以得出这么一个结论£º

      在ToNumber情况下£¬如果valueOf和toString返回的都不是原始数据类型£¬那么js会抛出异常£¬提示无法将引用类型转换原始数据类型¡£

      根据三组代码的运行的结果£¬我们最后总结一下£º

      在ToNumber情况下£¬js会优先调用valueOf£¬如果valueOf返回的不是原始数据类型£¬则会接着调用toString£¬如果toString返回的也不是原始数据类型£¬js会抛出一个异常£¬提示无法将引用类型转换原始数据类型¡£

      具体流程图如下£º

      ToString

      看个栗子🌰£º

      const obj = {
       toString(){
        console.log('调用了toString');
        return 'Hello,Teacher Cang!';
       },
       valueOf(){
        console.log('调用了valueOf');
        return 12345;
       }
      }
      console.log(String(obj)); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了toString
      Hello,Teacher Cang!

      通过上面的代码的运行结果£¬我们得出这么一个结论£º

      在ToString情况下£¬toString的优先级大于valueOf¡£

      同样我们看一下£¬toString返回的值不是原始数据类型时会怎样£º

      const obj = {
       toString(){
        console.log('调用了toString');
        return {};
       },
       valueOf(){
        console.log('调用了valueOf');
        return 'Hello,Teacher Cang!';
       }
      }
      console.log(String(obj)); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了toString
      调用了valueOf
      Hello,Teacher Cang!

      根据运行结果我们可以得出£º

      在ToString情况下£¬如果toString返回的不是原始数据类型£¬则会自动调用valueOf¡£

      最后我们看一下极端情况£¬二者返回的都不是原始数据类型£º

      const obj = {
       toString(){
        console.log('调用了toString');
        return {};
       },
       valueOf(){
        console.log('调用了valueOf');
        return {};
       }
      }
      console.log(String(obj)); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了toString
      调用了valueOf
      Uncaught TypeError: Cannot convert object to primitive value

      我们又发现£º

      在ToString情况下£¬如果toString和valueOf返回的都不是原始数据类型£¬那么js会抛出异常£¬提示无法将引用类型转换原始数据类型¡£

      我们将三个结论综合一下£º

      在ToString情况下£¬js会优先调用toString£¬如果toString返回的不是原始数据类型£¬则会接着调用valueOf£¬如果valueOf返回的也不是原始数据类型£¬js会抛出一个异常£¬提示无法将引用类型转换原始数据类型¡£

      具体流程图如下£º


      ¡°==¡±下的valueOf和toString的优先级

      从文章前面我们总结出来¡°==¡±的比较流程来看£¬引用类型转换成原始数据类型之后£¬如果是Sting类型的话£¬还要再次转成Number类型£¬因此¡°==¡±下的引用类型转换原始数据类型过程中£¬遵循ToNumber的优先级规则¡£

      const obj = {
       toString(){
        console.log('调用了toString');
        return 'Hello,Teacher Cang!';
       },
       valueOf(){
        console.log('调用了valueOf');
        return 12345;
       }
      }
      console.log(obj==12345); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了valueOf
      true
      const obj = {
       toString(){
        console.log('调用了toString');
        return 12345;
       },
       valueOf(){
        console.log('调用了valueOf');
        return {};
       }
      }
      console.log(obj==12345); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了valueOf
      调用了toString
      true
      const obj = {
       toString(){
        console.log('调用了toString');
        return {};
       },
       valueOf(){
        console.log('调用了valueOf');
        return {};
       }
      }
      console.log(obj==12345); 
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了toString
      调用了valueOf
      Uncaught TypeError: Cannot convert object to primitive value

      ¡°==¡±之外的类型转换

      ¡°==¡±号只涉及到了ToPrimitive和ToNumber这两种转换£¬ToBoolean和ToString这两个没有涉及到的我们也介绍一下¡£

      ToBoolean

      对于ToBoolean£¬我们只需要记住几个特例是转成false的£¬其余的皆为true¡£

      Boolean('') => false
      Boolean(undefined) => false
      Boolean(null) => false
      Boolean(0) => false 

      ToString

      Number to String

      Number转String之前£¬首先会做一个去0和补0的操作£¬然后再去转成String类型¡£

      String(1.234) => "1.234"
      String(NaN) => "NaN"
      String(.1234) => "0.1234"
      String(1.23400) => "1.234"

      Boolean to String

      String(true) => "true"
      String(false) => "false"

      null和undefined to String

      String(null) => "null"
      String(undefined) => "undefined"

      引用类型 to String

      引用类型先ToPrimitive转换成原始数据类型£¬若转换后的原始数据类型不是String类型£¬再做String类型的转换¡£

      const obj = {
       toString(){
        console.log('调用了toString');
        return true;
       }
      }
      console.log(String(obj))
      
      控制台输出结果£º
      >>>>>>>>>>>>>>>>>>
      调用了toString
      "true"

      总结

      ¡°==¡±下的类型转换£¬要分为两种情况来考虑¡£第一种£¬原始数据类型£»第二种£¬引用类型¡£原始数据类型中String类型和Boolean类型是需要转换成Number类型再去比较的£¬而引用类型则需要先转换成原始数据类型再进行后续的转换¡£搞清整个流程之后£¬我们再去理解¡°==¡±涉及到的ToNumber和ToPrimitive是如何进行转换的¡£按照这样子的理解步骤走£¬我们对¡°==¡±隐藏下的类型转换会有比较清晰的认识¡£另外£¬¡°==¡±不涉及到ToString和ToBoolean的类型转换£¬在文章的后面部分我也?#30001;先?#20102;£¬希望可以给小伙伴们一个更加全面的类型转换的认识¡£最后附上完整的¡°==¡±类型转换的流程图£º

      总结

      以上就是这篇文章的全部内容了£¬希望本文的内容对大家的学习或者工作具有一定的参考学习价值£¬谢谢大家对脚本之家的支持¡£

      相关文章

      最新评论

      3dÊÔ»úºÅÖвÊÍø

        1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
          <output id="hzk7v"></output>
        2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
        3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

            1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
              <output id="hzk7v"></output>
            2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
            3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>