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

  • 相关阅读:
    ORACLE 查看进程数,已执行任务数, 剩余任务数,删除指定任务
    ORACLE 收集统计整个用户数据
    解决Hystrix dashboard Turbine 一直 Loading…… 及其他坑
    利用 Maven 构造 Spring Cloud 微服务架构 模块使用 spring Boot构建
    AES加解密
    JAVA POI XSSFWorkbook导出扩展名为xlsx的Excel,附带weblogic 项目导出Excel文件错误的解决方案
    JAVA 文件的上传下载
    shell启停服务脚本模板
    JAVA 设计模式之 原型模式详解
    JAVA 设计模式之 工厂模式详解
  • 原文地址:https://www.cnblogs.com/daysme/p/6408682.html
Copyright © 2011-2022 走看看