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,超强推荐base.js
Dec 23 Javascript
JavaScript四种调用模式和this示例介绍
Jan 02 Javascript
jquery实现平滑的二级下拉菜单效果
Aug 26 Javascript
Vue.js学习笔记之 helloworld
Aug 14 Javascript
javascript cookie的基本操作(添加和删除)
Jul 24 Javascript
JavaScript的Object.defineProperty详解
Jul 09 Javascript
js实现随机div颜色位置 类似满天星效果
Oct 24 Javascript
JS实现动态无缝轮播
Jan 11 Javascript
基于js实现逐步显示文字输出代码实例
Apr 02 Javascript
Openlayers显示地理位置坐标的方法
Sep 28 Javascript
Vue过滤器,生命周期函数和vue-resource简单介绍
Jan 12 Vue.js
vue-cil之axios的二次封装与proxy反向代理使用说明
Apr 07 Vue.js
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中文本数据翻页(留言本翻页)
2006/10/09 PHP
PHP面向对象法则
2012/02/23 PHP
PHP关联数组的10个操作技巧
2013/01/21 PHP
php读取csv文件并输出的方法
2015/03/14 PHP
PHP实现一个轻量级容器的方法
2019/01/28 PHP
phpmyadmin在宝塔面板里进不去的解决方案
2020/07/06 PHP
TNC vs IO BO3 第二场2.13
2021/03/10 DOTA
javascript 弹出层组件(升级版)
2011/05/12 Javascript
获取元素距离浏览器周边的位置的方法getBoundingClientRect
2013/04/17 Javascript
JS判断浏览器是否支持某一个CSS3属性的方法
2014/10/17 Javascript
jQuery中nextUntil()方法用法实例
2015/01/07 Javascript
jquery实现动态操作select选中
2015/02/11 Javascript
js+jquery常用知识点汇总
2015/03/03 Javascript
JavaScript转换二进制编码为ASCII码的方法
2015/04/16 Javascript
JavaScript实现的经典文件树菜单效果
2015/09/08 Javascript
jQuery simpleModal插件的使用介绍
2016/08/30 Javascript
vue.js 左侧二级菜单显示与隐藏切换的实例代码
2017/05/23 Javascript
JavaScript对象_动力节点Java学院整理
2017/06/23 Javascript
Webpack实战加载SVG的方法
2017/12/26 Javascript
vue-cli2.9.3 详细教程
2018/04/23 Javascript
vue自动化表单实例分析
2018/05/06 Javascript
新手入门js闭包学习过程解析
2019/10/08 Javascript
javascript实现画板功能
2020/04/12 Javascript
Python使用BeautifulSoup库解析HTML基本使用教程
2016/03/31 Python
Python基于回溯法子集树模板解决m着色问题示例
2017/09/07 Python
Python二叉树定义与遍历方法实例分析
2018/05/25 Python
利用python实现短信和电话提醒功能的例子
2019/08/08 Python
CSS3+font字体文件实现圆形半透明菜单具体步骤(图解)
2013/06/03 HTML / CSS
COACH德国官方网站:纽约现代奢侈品牌,1941年
2018/06/09 全球购物
MyBag中文网:英国著名的时尚包袋电商零售网站
2020/07/31 全球购物
进程的查看和调度分别使用什么命令
2013/12/14 面试题
幼儿园中班上学期评语
2014/04/18 职场文书
孝敬父母的活动方案
2014/08/31 职场文书
教学副校长工作总结
2015/08/13 职场文书
MYSQL 运算符总结
2021/11/11 MySQL
一条慢SQL语句引发的改造之路
2022/03/16 MySQL