undefined!=false之解 及==比较的规则
JS中有一个基本概念就是:
JavaScript中undefined==null
但undefined!==null
undefined与null转换成布尔值都是false
如果按照常规想法,比如下面的代码
- var a=1;
- alert(Boolean(a));//返回true
- //那么下面的代码也应该返回true
- alert(1==true);
- //但肯定的,下面的代码会返回false
- alert(1===true);
但对于下面的代码,估计会让大部分JS程序员疑惑
- alert(123==true);//为什么返回false
- alert(Boolean(undefined));//outputs false
- alert(Boolean(null));//outputs false
- alert(undefined==false);//竟然返回false
- alert(null==false);//竟然也返回false
至于其原因,下面作一个尝试性的解析(是尝试性的解析)
首先看看JS中的==比较是如何比较的
对于标量,“==”直接比较其中的值就行了
而对于两个对象(这里特指除去原始值的对象……因为在JS可以说一切皆对象)
则是比较其引用
因此对于两个对象的比较,看它们是不是同一个对象,是不需要用===(严格相等,值相等且类型相同)的
再深入分析下JS对于标量应用==比较时的情况
对于相同类型的两个标量的比较,除了NaN比较特殊之外(NaN==NaN返回false),都没什么疑点
而对于类型不同的两个标量的比较,JS就有一套严格的规则,这规则JS解析引擎具体怎样执行的,抱歉,还没去看JS解析引擎的源代码呢,这里只好对其表现作个总结
1.将Boolean,Number,String这三种类型进行不同类型的==比较时,其规则是,总将两边的值转换成数字,再看看转换结果数字是否相等
如下代码
- alert(1==true);//true转换成数字也是1
- alert('1'==true);//将字符串'1'与true都转换成数字
- alert('abc'==true);//虽然字符串'abc'转换成布尔值是true,但这里会返回false
- //因为'abc'转换成数字是NaN,而true转换成数字是1
- alert(123=='123');//同理,true
而undefined与null,它们是简单类型还是引用类型呢?
将上面的规则 应用于undefined与null时就不正确了,在解析之前,先看看==比较的其它形式
JS中简单类型与引用类型进行==比较的情况
这种比较与是有规则的,并且可以用代码来验证JS内部的执行情况
将一个简单类型(这里指除undefined与null的值)与一个对象比较时,
先调用对象的valueOf方法,以期待返回一个标量,如果对象的valueOf方法返回的仍然是一个复合对象的话
就接着调用对象的toString方法以期待返回一个标量,如果仍然没有返回标量的话,就判为不相等
如果valueOf或toString方法之一返回一个标量,就用这个标量同==另一边的标量进行比较
- var obj={};
- alert(obj=="abc");//false
- obj.toString=function () {
- return 'abc';
- };
- alert(obj=='abc');//这时就返回true了
- alert(obj==123);//false
- obj.valueOf=function () {return 123};
- alert(obj==123);//true!!!
- obj.valueOf=undefined;//先将这个方法清空掉,以免受上面的代码影响
- alert(obj==true);//false
- obj.valueOf=function () {
- return 1;//只要返回一个能转换成布尔值的标量就行了,1或true都行,都表示true
- };
- alert(obj==true);//true!!!!
事实上还可以用下面的代码进行验证,将一个复合对象与标量进行比较时,总会先调用对象的valueOf,
valueOf方法返回不是一个标量的话还会接着调用toString方法
- var obj={
- toString:function () {
- alert('valueOf方法没有返回标量,我会被调用');
- },
- valueOf:function () {
- alert('我先被调用,Object的valueOf方法默认实现是返回对象自身');
- }
- };
- 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都转换成数字再进行比较
也就是说
- var a="true";
- var b=true;
- alert(a==b);
- //结果等同于下面的代码
- alert(Number(a)===Number(b));
而如果a是Number,String,Boolean这三种类型中的一种,而b是一个复合对象时(Object,Array等)
则对b执行ToPrimitive操作(这步是JS解释器执行的)
即
- var a="abc";
- var b={};
- alert(a==b);
- //上面的一行代码在JS解析时将被解释成
- //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
undefined!=false之解 及==比较的规则的更多相关文章
- JavaScript:undefined!=false之解 及==比较的规则
JS中有一个基本概念就是: JavaScript中undefined==null 但undefined!==null undefined与null转换成布尔值都是false 如果按照常规想法,比如下面 ...
- undefined == false 么
今天碰到个问题,我需要去判断 undefined == false 会返回什么,想当然的以为会返回true,但是结果却返回的是false,这我就有点晕了,不是说undefined.null.0.NaN ...
- 0,null,undefined,[],{},'',false之间的关系
0与一些虚值的比较: 0与false 0==false true 0与'': =='' true 0与[]: ==[] true 0与NaN: 0==NaN false 0与undefined 0== ...
- null,undefined.'',false关系
null == undefined //truefalse =='' //true boolean类型跟其它类型==时,会转换成Number类型 Number类型跟String类型==时,string ...
- ‘true’==true返回false详解
JavaScript高级程序设计(第3版) 第三章非常完整地解释了原因. 3.5.7 相等操作符 在转换不同的数据类型时,相等和不相等操作符遵循下列基本规则: . 如果有一个操作数是布尔值,则在比较 ...
- Scrapy框架——介绍、安装、命令行创建,启动、项目目录结构介绍、Spiders文件夹详解(包括去重规则)、Selectors解析页面、Items、pipelines(自定义pipeline)、下载中间件(Downloader Middleware)、爬虫中间件、信号
一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可 ...
- javascript return false 详解
在大多数情况下,为事件处理函数返回false,可以防止默认的事件行为.例如,默认情况下点击一个<a>元素,页面会跳转到该元素href属性指定的页. Return False 就相当于终止符 ...
- javascript事件中'return false'详解
浏览器中有很多异步事件,如click,mouseenter,mouseover等等,当用户执行相应操作之后,触发这个事件,然后执行相应的事件处理函数,一般情况下,我们可以通过三种方式给元素添加事件处理 ...
- null、undefined、false、0相等性比较
之前在看<JavaScript权威指南>的时候看到三个相等性比较的式子: null == undefined ;// ==>true undefined == false;// == ...
随机推荐
- mysql 权限管理 针对某个库 某张表 授权 tables_priv表
精确到表级别 针对db1的t3表 授予select权限 mysql> grant select on db1.t3 to 'mike'@'localhost'; Query OK, rows a ...
- Intel 设计缺陷背后的原因是什么? | Linux 中国
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79386769 wx_fmt=jpeg& ...
- [LeetCode] 721. Accounts Merge_Medium tag: DFS recursive
Given a list accounts, each element accounts[i] is a list of strings, where the first element accoun ...
- 20165324 《网络对抗技术》week1 Kali的安装与配置
20165324 <网络对抗技术>week1 Kali的安装与配置 安装过程 VMware安装过程省略 kali 光盘映像文件的下载 新建虚拟机,并导入. 安装Tools 在菜单中,选择虚 ...
- TempData["a"]多个Action方法之前共享数据
ViewData["a"]只可以在自己视图的页面里被访问,但TempData["a"]可以多个Action方法之前共享数据,比如在 @{Html.RenderA ...
- mysql数据库环境配置中部分问题解决办法
注:原文地址:https://www.cnblogs.com/hezhuoheng/p/9366630.html 其中最重要的,是三个原则:命令按顺序输入.删除了ini(这个不是原则,是我解决问题的一 ...
- windows中xcopy命令详解
一.格式: 二.举例说明: 1.复制文件,文件路径有空格的,那么就使用双引号括起来.如果目标路径已经有相同文件了,使用覆盖方式而不进行提示.在复制文件的同时也复制空目录或子目录 xcopy ...
- 奋斗史-IT女生是怎样炼成的
IT女生的奋斗史 终于来到了毕业季,感觉有点伤感! 记得11年来到大学的时候,还是那么懵懂,什么都不懂,几乎连电脑的基本操作都不会!自己小时候虽然家里穷,但是从小就觉得“软件”是个很神奇的东西,很了不 ...
- DBus学习网站
http://blog.csdn.net/thonrbirdxb/article/details/11482007 DBus的基本资料可以参考 DBus学习笔记(博客园) http://dotnet. ...
- Django框架----数据库表的单表查询
一.添加表记录 对于单表有两种方式 # 添加数据的两种方式 # 方式一:实例化对象就是一条表记录 Frank_obj = models.Student(name ="海东",cou ...