zoukankan      html  css  js  c++  java
  • undefined!=false之解 及==比较的规则

    JS中有一个基本概念就是: 
    JavaScript中undefined==null 
    但undefined!==null 
    undefined与null转换成布尔值都是false 
    如果按照常规想法,比如下面的代码 

    Js代码  收藏代码
    1. var a=1;  
    2. alert(Boolean(a));//返回true  
    3. //那么下面的代码也应该返回true  
    4. alert(1==true);  
    5.   
    6. //但肯定的,下面的代码会返回false  
    7. alert(1===true);  




    但对于下面的代码,估计会让大部分JS程序员疑惑 

    Js代码  收藏代码
    1. alert(123==true);//为什么返回false  
    2.   
    3.   
    4. alert(Boolean(undefined));//outputs false  
    5. alert(Boolean(null));//outputs false  
    6.   
    7. alert(undefined==false);//竟然返回false  
    8. alert(null==false);//竟然也返回false  


    至于其原因,下面作一个尝试性的解析(是尝试性的解析) 

    首先看看JS中的==比较是如何比较的 
    对于标量,“==”直接比较其中的值就行了 
    而对于两个对象(这里特指除去原始值的对象……因为在JS可以说一切皆对象) 
    则是比较其引用 
    因此对于两个对象的比较,看它们是不是同一个对象,是不需要用===(严格相等,值相等且类型相同)的 


    再深入分析下JS对于标量应用==比较时的情况 
    对于相同类型的两个标量的比较,除了NaN比较特殊之外(NaN==NaN返回false),都没什么疑点 
    而对于类型不同的两个标量的比较,JS就有一套严格的规则,这规则JS解析引擎具体怎样执行的,抱歉,还没去看JS解析引擎的源代码呢,这里只好对其表现作个总结 
    1.将Boolean,Number,String这三种类型进行不同类型的==比较时,其规则是,总将两边的值转换成数字,再看看转换结果数字是否相等 
    如下代码 

    Js代码  收藏代码
    1. alert(1==true);//true转换成数字也是1  
    2. alert('1'==true);//将字符串'1'与true都转换成数字  
    3.   
    4. alert('abc'==true);//虽然字符串'abc'转换成布尔值是true,但这里会返回false  
    5. //因为'abc'转换成数字是NaN,而true转换成数字是1  
    6.   
    7. alert(123=='123');//同理,true  



    而undefined与null,它们是简单类型还是引用类型呢? 
    将上面的规则 应用于undefined与null时就不正确了,在解析之前,先看看==比较的其它形式 

    JS中简单类型与引用类型进行==比较的情况 
    这种比较与是有规则的,并且可以用代码来验证JS内部的执行情况 
    将一个简单类型(这里指除undefined与null的值)与一个对象比较时, 
    先调用对象的valueOf方法,以期待返回一个标量,如果对象的valueOf方法返回的仍然是一个复合对象的话 
    就接着调用对象的toString方法以期待返回一个标量,如果仍然没有返回标量的话,就判为不相等 
    如果valueOf或toString方法之一返回一个标量,就用这个标量同==另一边的标量进行比较 

    Js代码  收藏代码
    1. var obj={};  
    2. alert(obj=="abc");//false  
    3. obj.toString=function () {  
    4.     return 'abc';  
    5. };  
    6. alert(obj=='abc');//这时就返回true了  
    7.   
    8. alert(obj==123);//false  
    9. obj.valueOf=function () {return 123};  
    10. alert(obj==123);//true!!!  
    11.   
    12. obj.valueOf=undefined;//先将这个方法清空掉,以免受上面的代码影响  
    13. alert(obj==true);//false  
    14. obj.valueOf=function () {  
    15.   return 1;//只要返回一个能转换成布尔值的标量就行了,1或true都行,都表示true  
    16. };  
    17. alert(obj==true);//true!!!!  


    事实上还可以用下面的代码进行验证,将一个复合对象与标量进行比较时,总会先调用对象的valueOf, 
    valueOf方法返回不是一个标量的话还会接着调用toString方法 

    Js代码  收藏代码
    1. var obj={  
    2.     toString:function () {  
    3.         alert('valueOf方法没有返回标量,我会被调用');  
    4.     },  
    5.     valueOf:function () {  
    6.         alert('我先被调用,Object的valueOf方法默认实现是返回对象自身');  
    7.     }  
    8. };  
    9. alert(1==obj);//可以看到执行次序  



    那么讲了这么多,这和undefined!=false有什么关系呢? 
    JS中的==对两边的对象进行比较时,undefined将被转换成数字,也就是说,undefined被看成基本值 
    而又由于undefined转换成数字为NaN,所以将Number,String,Boolean这三种类型与undefined比较时,总是返回false 
    而对于null,JS则将其当成对象来比较,即尝试调用null的valueOf与toString方法,再将返回的结果与另一个值进行比较,可以推断null==false返回false的原因是因为null的valueOf实现导致的 
    由于null没有valueOf与toString方法,因此始终返回false 
     
    ECMAScript规范是怎么说的? 
    ECMAScript规范中指出,a与b进行比较,如果a与b是Number,String,Boolean这三种类型中的一种, 
    并且a与b的类型不同,那么就将a与b都转换成数字再进行比较 
    也就是说 

    Js代码  收藏代码
    1. var a="true";  
    2. var b=true;  
    3. alert(a==b);  
    4. //结果等同于下面的代码  
    5. alert(Number(a)===Number(b));  


    而如果a是Number,String,Boolean这三种类型中的一种,而b是一个复合对象时(Object,Array等) 
    则对b执行ToPrimitive操作(这步是JS解释器执行的) 
    即 

    Js代码  收藏代码
    1. var a="abc";  
    2. var b={};  
    3. alert(a==b);  
    4. //上面的一行代码在JS解析时将被解释成  
    5. //a==ToPrimitive(b);  


    而这个ToPrimitive方法的实现,正是依次去调用对象的valueOf,toString方法,直到其中一个方法返回一个基本值 
    如果这两个方法没有返回基本值 ,那就认定不相等 

    而当a和b都是复合对象时,就很简单,就看a和b是不是同一个对象的引用! 

    而对于将undefined,null与其它类型进行比较的,则没具体说,只说了将 
    任何基本类型与Boolean类型比较时,会将其转换成数字(与前面的规则一样) 


    总结 
    Number,Boolean,String,Undefined这几种基本类型混合比较时,会将其转换成数字再进行比较 
    基本类型与复合对象进行比较时,会先将复合对象转换成基本类型(依次调用valueOf与toString方法)再进行比较 
    undefined被当成基本类型,undefined转换成数字是NaN,因此undefined与除null之外的其它类型值进行比较时始终返回false(注意NaN==NaN返回false) 
    null被当成复合对象,由于null没有valueOf与toString方法,因此和除了undefined之外的其它类型值进行比较时始终返回false 

    引:http://www.iteye.com/topic/696802

  • 相关阅读:
    SpringMVC+Shiro权限管理(转载)
    面试常见问题(转载)
    JavaScript 五种(非构造方式)继承
    JavaScript 五种(构造方式)继承
    Quartz.Net 基于XML配置启动
    jexus防止产生 *.core文件
    Last-Modified、ETag、Expires和Cache-Control
    正则表达式记录
    C# 操作mongodb子文档
    ASP.NET Core "完整发布,自带运行时" 到jexus
  • 原文地址:https://www.cnblogs.com/daysme/p/6408682.html
Copyright © 2011-2022 走看看