深入探究JavaScript中的比较问题
先用最近遇到的几个问题做引子:
1 console.log(null==undefined); //true
2 console.log(null==false);//false
3 console.log(null==0);//false
4 console.log(0==undefined);//false
5 console.log(false==undefined); //false
6 console.log([]==![]);//true
各位读者如果不确定的话,可以在各自的浏览器中实验一下。
怎么样?答案和自己想的一致吗?如果不一致,那就跟随笔者探索一下其中的奥秘吧!
首先我们来分析一下undefined和null的区别。
首先来看下面这个例子:
Number(null)
//0
10+null
//10
这样看来,null被设计成可以自动转为0.
JavaScript的最初版本是这样区分的,null是一个表示“无”的对象,转为数值时为0;undefined是一个表示“无”的原始值,转为数值时为NaN。
null表示“没有对象”,即该处不应该有值。典型用法是:
作为函数的参数,表示该函数的参数不是对象。
作为对象原型链的终点。
Object.getPrototypeOf(Object.prototype)
// null
undefined表示“缺少值”,就是此处应该有一个值,但是还没有定义。典型用法是:
变量被声明了,但没有赋值时,就等于undefined。
调用函数时,应该提供的参数没有提供,该参数等于undefined。
对象没有赋值的属性,该属性的值为undefined
函数没有返回值时,默认返回undefined
var i;
i //undefined function f(x){console.log(x)}
f() //undefined var o=new Object();
o.p //undefined var x=f();
x //undefined
那么为什么null==undefined呢?
ECMAScript认为,undefined是从null派生出来的,所以把它们定义为相等的。但是,如果在一些情况下,我们一定要区分这两个值,那应该怎么办呢?可以使用下面的两种方法。
alert(null===undefined);
alert(typeof null == typeof undefined)
此时,我们已经解决了第5个问题,那么其他的如何解释呢?
下面是摘自stackflow上大神的解释。
The Abstract Equality Comparison Algorithm
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
If Type(x) is the same as Type(y), then
1.1 If Type(x) is Undefined, return true.
1.2 If Type(x) is Null, return true.
1.3 If Type(x) is Number, then
If x is NaN, return false.
If y is NaN, return false.
If x is the same Number value as y, return true.
If x is +0 and y is −0, return true.
If x is −0 and y is +0, return true.
Return false.
1.4 If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.
1.5 If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
1.6 Return true if x and y refer to the same object. Otherwise, return false.If x is null and y is undefined, return true.
If x is undefined and y is null, return true.
If Type(x) is Number and Type(y) is String,return the result of the comparison x == ToNumber(y).
If Type(x) is String and Type(y) is Number,return the result of the comparison ToNumber(x) == y.
If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
If Type(x) is either String or Number and Type(y) is Object,return the result of the comparison x == ToPrimitive(y).
If Type(x) is Object and Type(y) is either String or Number,return the result of the comparison ToPrimitive(x) == y.
基于以上规则,我们再来看看最初的题目:
以第6题为例:
[]是数组,而![]是boolean值。当你使用==比较两个不同类型的对象时需要转化为可比较的类型,根据上述规则第7条,使用ToNumber转化后,![]返回0,[]返回0,所以为true。
深入探究JavaScript中的比较问题的更多相关文章
- 探究JavaScript中的五种事件处理程序
探究JavaScript中的五种事件处理程序 我们知道JavaScript与HTML之间的交互是通过事件实现的.事件最早是在IE3和Netscape Navigator 2中出现的,当时是作为分担服务 ...
- 探究javascript对象和数组的异同,及函数变量缓存技巧
javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...
- Javascript中String()与new String()的差异
这里主要关注的是值类型和引用类型. 我们知道在javascript中的变量在内存中的存储有两种形式,值类型存储和引用类型存储. 通常可以进行值存储的包括 字符串类型,布尔值类型,数字类型,他们都包含 ...
- JavaScript中的事件对象
JavaScript中的事件对象 JavaScript中的事件对象是非常重要的,恐怕是我们在项目中使用的最多的了.在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含这所有与事件有 ...
- JavaScript中以构造函数的方式调用函数
转自:http://www.cnblogs.com/Saints/p/6012188.html 构造器函数(Constructor functions)的定义和任何其它函数一样,我们可以使用函数声明. ...
- javascript中var、let和const的区别
在javascript中,var.let和const都可以用来声明变量,那么三者有什么区别呢?要回答这个问题,我们可以从先想想:三种不同的声明会影响变量的哪些方面?这些方面也就是变量的特性,那么变量有 ...
- Javascript中的继承与Prototype
之前学习js仅仅是把w3school上的基本语法看了一次而已,再后来细看书的时候,书中会出现很多很多没有听过的语法,其中一个就是js的继承以及总能看到的prototype.我主要在看的两本js书是&l ...
- 漫谈JavaScript中的提升机制(Hoisting)
前言 刚接触到JavaScript的时候,便知道JavaScript是按顺序执行的,是如浏览器的解析DOM树一样的流程,解析DOM结构的时候,如果遇到JS脚本或者外联脚本便会停止解析,继续下载脚本之后 ...
- 详解JavaScript中的原型
前言 原型.原型链应该是被大多数前端er说烂的词,但是应该还有很多人不能完整的解释这两个内容,当然也包括我自己. 最早一篇原型链文章写于2019年07月,那个时候也是费了老大劲才理解到了七八成,到现在 ...
随机推荐
- find命令基本使用一览
find命令相对于locate这种非实时查找的搜索命令,大大增加了我们搜索的便捷度以及准确性:并且能够方便的帮助我们对大文件.特定类型的文件查找与删除,特别是有超多小碎文件的时候,更是方便至极.... ...
- php中的全局变量引用
全局变量在函数外部定义,作用域为从变量定义处开始,到本程序文件的末尾.但和其他语言不同,php的全局变量不是自动设为可用的,在php中函数可以视为单独的程序片段,局部变量会覆盖全局变量的能见度,因此, ...
- 从入行到现在(.net)
每次写东西都不知道怎么去开头.因为一想到要写东西.脑子里面浮现出来的开头就太多. 进园子很久从开始只是关注别人讲的技术,别人讲的基础,到现在更多的去看大家的随笔和新闻.这两年我从零基础的外行人逐渐进入 ...
- 利用SQL语句给字段加注释
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'角色Id',--注释名称 @level0type=N'SCHEMA' ...
- 总结Qt中经常出现的一些问题
1.Qt中用高版本打开低版本的工程 编译时出现错误 : C1189: #error : "This file was generated using the moc from 4.7.0. ...
- c# web页面乱码
1.在web.config中加入:<globalization requestEncoding="GB2312" responseEncoding="GB2312& ...
- 2014年12月20日00:33:14-遮罩+进度条-extjs form.isvalid
1.Extjs : 遮罩+进度条 2.Extjs: extjs form.isvalid http://stackoverflow.com/questions/19354433/extjs-form- ...
- Glibc和GCC,ARM-LINUX-GCC的关系
看到有些贴子/blog上提到「Glibc编译器」,这是个错误的用语.Glibc不是编译器,Glibc不是编译器,Glibc不是编译器.重要的事情说三遍.GCC才是编译器.
- OpenGL中的深度、深度缓存、深度测试及保存成图片
1.深度 所谓深度,就是在openGL坐标系中,像素点Z坐标距离摄像机的距离.摄像机可能放在坐标系的任何位置,那么,就不能简单的说Z数值越大或越小,就是越靠近摄像机. 2.深度缓冲区 深度缓冲区原理就 ...
- 关于C++对汉字拼音的处理
直到目前我没有找到比较合适的输入汉字输出拼音的函数,那么根据网上流传的几个源码进行了改编,写成了输入汉字输出拼音的函数.对于此函数不能说强大,但是至少稳定可用,输出结果还没有发现什么错误. 那么下面我 ...