javascript中的相等操作符(==与===区别)


Posted in Javascript onDecember 21, 2019

1.前言

我们在编程的过程中,经常会遇到判断两个变量是否相等的情况,ECMAscript提供了两种相等操作符”==”和”===”来判断,这两种操作都会返回一个boolean值。一般来说,我们把”==”称之为相等,称”===”为全等。当两相比较的两个变量数据类型一致时,情况比较简单,而当操作符两边的变量类型不一致,甚至其中的某个变量是对象时,情况就比较复杂了,下面分别介绍当操作数类型不同时运算结果会怎么样。

2.全等操作符 “===”

全等操作符”===”的情况相对来说比较简单。当用全等操作符”===”来判断时,首先检查操作符两边操作数数据类型是否一致,若不一致,则直接返回false,否则,才进行下一步判断。如果是两个boolean的比较,则”===”两边必须同为true或同为false,才可以返回true,否则返回false.若两相比较的是数字,那么只有当这两个数字大小相等时才会返回true,否则返回false。如果要比较的两个变量是字符串,先比较两个字符串的长度length是否相等,如果长度不一样,则返回false,如果相等,则从两个变量的第一个字符开始比较是否相等,一直比较到最后一位,如果其中的某一位不想等,则返回false,否则返回true,(注意:字符串的比较是不会忽略空格的,所以在比较两个字符串是否相等时,为确保安全,应该先去除空格,然后把两个字符串同转为大写或者小写之后再进行比较)。而null只有在null===null的情况下才会返回true,其它情况都返回false,同样,undefined只有在undefined===undefined的情况下才会返回true,否则返回false。如:

true === 1    //false
"1" === 1    //false
 
//boolean的比较
true === true  //true
true === false  //false

//string的比较
"hello" === "helloworrld" //false
"hello" === "world" //false
"hello" === " hello" //false
"hello" === "hellO" //false
"hello" === "hello" //true

//number的比较
1 === 1  //true
1 === 1.0 //true
1 === 1.2 //false

//null和undefined的比较
undefined === undefined  //true
null === null       //true
undefined === null    //false,两者在"=="时才返回true

如果进行”===”比较的两个操作数不是基本类型值,而是两个对象,这时候判断依据就是,判断这两个变量是否是”同一个”对象

var a,b,c;
a = b = {
	name : '柳轻侯',
	city : '南京'
};
c = {
	name : '柳轻侯',
	city : '南京'
};
a === b   //true
a === c   //false

两个对象仅仅”长得一样”是不够的,a和c都是Object实例,且两者拥有相同的属性和值,可是这两个却不是”同一个”对象,因为实际上a和c指向了两个不同的实例,所以这两个对象是不全等的。而a和b却是指向了同一个对象,换个说法,a和b是同一个对象的不同别名,他们实际上指向的对象是完全相同的,所以a === b。”!==” 与 “===” 比较规则一样,在此不再赘述。

3.相等操作符”==”

全等操作符在进行判断的时候,如果两个变量的类型不同,则直接返回false,而与此不同,”==”相等操作符在判断的时候,如果两个变量的类型不同,则会做一个隐式的类型转换,把要比较的两个值转化为相同的类型再做比较,那么这种转化规则是怎么样的?

在转化不同数据类型时,相等和不等操作符遵循下面的基本规则

  • 如果其中一个操作数是是boolean值,则在比较之前会先将boolean值转化为number值,true转化为1,false转为0;
  • 如果其中一个操作数是string类型,而另一个是number类型,则在比较之前先将string类型转化为number类型再进行判断;
  • 在比较之前,undefined和null是不会转为其他值进行比较的;
  • 如果其中一个操作数是对象,而另一个是基本类型值,则在比较之前先将对象转为基本类型值,然后再依据前面的规则进行后续的比较;

两个操作数在比较时遵循下列规则

  • undefined和null是相等的,即:undefined == null;
  • 如果有一个操作数是NaN,那么返回false,即使两个操作数都是NaN,也会返回false;
  • 如果两个操作数是对象,则比较规则跟”===”的比较规则是一样的,除非这两个操作数是同一个对象,则返回true,否则返回false;

此处需要注意的是,NaN == NaN是返回false的,NaN意思是 not a number,也就是说该操作数是一个非数字,这个非数字是不确定的,它的值是未知的,甚至可能根本就不能用javascript的语法表示出来,这样一个未知量是不能用来进行特定比较的,两个未知的东西,如果不能确定它的值是什么,当然不能说 NaN == NaN。那么既然不能用”==”来比较,我们怎么去判定一个变量是不是NaN呢 ,既然不能用相等来判定,那么不妨反其道而行之,用”!=”来判定,判定一个变量是否不等于NaN。比如:

//如果需要判定一个变量是不是NaN,可以如下
//a是你需要判定的变量
if((typeof a === "number") && a != NaN ){  //此处需要注意,NaN也是number类型
	//TODO 
}

4.常见比较情况及其结果

null == undefined  // true 
"NaN" == NaN    // false 
5 == NaN      // false 
NaN == NaN     // false 
NaN != NaN     // true 
false == 0     // true 
true == 1      // true 
true == 2      // false 
undefined == 0   // false 
null == 0      // false
"5" == 5      // true

5.典型例题解析

![] == [] //true

这是一道比较容易令人困惑的题,按照正常的思维模式,对一个操作数逻辑取反,跟这个操作数本身的值是相对的,如果这个操作数本身的值是true,那么取反之后就是false,反之,如果这个操作数的值是false,那么对其逻辑取反之后就是true,无论如何也不会是同一个值,可是事实上却是![] == []。首先,![]的值是false,因为这里[]被当成了一个数组的实例,是一个对象,而对象都是真值,对其取反,得到一个假值,也就是false。其次看等号右边,[]是一个对象,要将其转为基本类型值,会先调用数组的valueOf方法,而数组的valueOf方法返回数组本身,没有得到一个基本值,这时候要继续调用数组的toString方法,得到一个””空字符串,所以这时候也就变成了false == “”是否为真的问题了,而根据前面的规则,如果有一个操作数为boolean值,会将其转为数值,false转化为0。进而,问题转化为0 == “”是否为真值的问题,当number和string比较时,会将string转为number,而””会转为0。最后,问题变演化成了0 == 0是否为真值,毋庸置疑,结果是true。这里要注意的就是![],它被当成了一个整体的逻辑值,是直接对对象进行取反,是一个假值,而不是先把[]转化为基本值再取反

6.小结

“==”在比较不同类型值得时候会进行隐式的类型转化,而”===”不会转化,全等一定相等,相等却不一定全等,这是一个充分不必要条件。undefined和null相等而不全等,且在相等比较的时候不会转化为其他类型的值。NaN是不等于NaN 的,要判断某个变量是不是NaN,要用”!=”。对象和非对象在进行比较的时候会先转为基本类型值然后再根据上面的规则进行比较。

7.参考资料

《javascript高级程序设计》
《javascript权威指南》

Javascript 相关文章推荐
JS 有名函数表达式全面解析
Mar 19 Javascript
jQuery EasyUI API 中文文档 - Calendar日历使用
Oct 19 Javascript
JS中toFixed()方法引起的问题如何解决
Nov 20 Javascript
一行命令搞定node.js 版本升级
Jul 20 Javascript
javascript常用代码段搜集
Dec 04 Javascript
jQuery实现dialog设置focus焦点的方法
Jun 10 Javascript
深入理解JavaScript中为什么string可以拥有方法
May 24 Javascript
利用Angular2 + Ionic3开发IOS应用实例教程
Jan 15 Javascript
微信小程序上传图片实例
May 28 Javascript
用npm安装vue和vue-cli,并使用webpack创建项目的方法
Sep 28 Javascript
vue项目中实现图片预览的公用组件功能
Oct 26 Javascript
VUE+node(express)实现前后端分离
Oct 13 Javascript
JavaScript中的相等操作符使用详解
Dec 21 #Javascript
高性能js数组去重(12种方法,史上最全)
Dec 21 #Javascript
ES6常用小技巧总结【去重、交换、合并、反转、迭代、计算等】
Dec 21 #Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
Dec 20 #Javascript
angularjs模态框的使用代码实例
Dec 20 #Javascript
推荐几个不错的console调试技巧实现
Dec 20 #Javascript
Vue+Node服务器查询Mongo数据库及页面数据传递操作实例分析
Dec 20 #Javascript
You might like
php设计模式 Proxy (代理模式)
2011/06/26 PHP
PHP列出MySQL中所有数据库的方法
2015/03/12 PHP
php把大写命名转换成下划线分割命名
2015/04/27 PHP
composer.lock文件的作用
2016/02/03 PHP
PHP-FPM 设置多pool及配置文件重写操作示例
2019/10/02 PHP
PHP数据源架构模式之表入口模式实例分析
2020/01/23 PHP
Extjs学习笔记之一 初识Extjs之MessageBox
2010/01/07 Javascript
利用谷歌地图API获取点与点的距离的js代码
2012/10/11 Javascript
javascript 手动给表增加数据的小例子
2013/07/10 Javascript
js 调用父窗口的具体实现代码
2013/07/15 Javascript
判断js中各种数据的类型方法之typeof与0bject.prototype.toString讲解
2013/11/07 Javascript
jQuery实现统计复选框选中数量
2014/11/24 Javascript
jQuery实现渐变弹出层和弹出菜单的方法
2015/02/20 Javascript
javascript获取当前的时间戳的方法汇总
2015/07/26 Javascript
javascript实现3D变换的立体圆圈实例
2015/08/06 Javascript
浅谈JavaScript中的分支结构
2016/07/01 Javascript
功能强大的Bootstrap效果展示(二)
2016/08/03 Javascript
老生常谈combobox和combotree模糊查询
2017/04/17 Javascript
jQuery查找和过滤_动力节点节点Java学院整理
2017/07/04 jQuery
微信小程序实现动态获取元素宽高的方法分析
2018/12/10 Javascript
如何利用node.js开发一个生成逐帧动画的小工具
2019/12/01 Javascript
JavaScript修改注册表实例代码
2020/01/05 Javascript
python 实现插入排序算法
2012/06/05 Python
使用wxpython实现的一个简单图片浏览器实例
2014/07/10 Python
Python六大开源框架对比
2015/10/19 Python
深入浅出分析Python装饰器用法
2017/07/28 Python
python 普通克里金(Kriging)法的实现
2019/12/19 Python
Python底层封装实现方法详解
2020/01/22 Python
基于Python爬取爱奇艺资源过程解析
2020/03/02 Python
英国邮购活的植物主要供应商:Gardening Direct
2019/01/28 全球购物
工程力学专业毕业生求职信
2013/10/06 职场文书
建筑装饰学院室内设计专业个人自我评价
2013/12/07 职场文书
新学期班主任寄语
2014/01/18 职场文书
思想品德课教学反思
2014/02/10 职场文书
好听的队名和口号
2014/06/09 职场文书
办公室班子四风问题对照检查材料
2014/10/04 职场文书