深入探究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月,那个时候也是费了老大劲才理解到了七八成,到现在 ...
随机推荐
- 使用startCoroutine制定倒计时
使用startCoroutine制定倒计时 using UnityEngine; using System.Collections; public class TimerCoroutine : Mon ...
- 玩转Android之在线视频播放控件Vitamio的使用
其实Android中自带的MediaPlayer本身就能播放在线视频,MediaPlayer结合SurfaceView播放在线视频也是不错的选择(如果你没有性能或者用户体验上的要求),关于MediaP ...
- iOS 跳转至 指定 StoryBoard 中 指定的 Scene
UIStoryboard *stryBoard=[UIStoryboard storyboardWithName:@"second" bundle:nil]; UIViewCont ...
- java_method_删除事务回滚
public String[] deleteEPGroup(String groupID, String groupName) { String[] operRes=new String[3]; if ...
- 黑色遮罩引导蒙版 CSS实现方式
一.微云的实现 网站有一些改动的时候,为了让用户熟知新的操作位置,往往会增加一个引导,常见的方式就是使用一个黑色的半透明蒙版,然后需要关注的区域是镂空的. 然后上周五我去微云转悠的时候,也看到了引导层 ...
- android 6.0特性翻译 --渣渣
所有关于Android 6.0 棉花糖的知识 上下文帮助 1.现在按压:不需要离开你正在运行的app或者访问的网站就可 获取帮助,仅仅触摸和按下Home按钮.(长按Home键,可以在 android ...
- Core Data(数据持久化)
Core Data可能是OS X和iOS中最容易被误解的框架之一了.为了帮助大家理解,我们将快速研究Core Data,来看一下它是关于什么的.为了正确使用Core Data, 有必要理解其概念.几乎 ...
- struts2类型转换中的错误处理
由于类型转换过程中有可能出现原始参数无法转换为目标类型的错误,所以struts2提供了类型转换中的异常处理机制. 在struts2的默认配置文件struts-default.xml中有如下一段配置代码 ...
- iOS控件——UIView与UIImageView播放动画的实现方法
1.UIView //初始状态 [UIView animateWithDuration:(int) animations:^{ //最终状态 }completion:^(BOOL finished){ ...
- PHP学习笔记(五)
关于Response header 的一些小知识: Host :address url, host 是浏览器给服务器提供的address标识.由于http协议是无状态的,服务器需要根据host的这个 ...