JavaScript中三个等号和两个等号你了解多少


Posted in Javascript onJuly 04, 2017

引子

众所周知,用在if条件判断语句中,js有六种假值:false, null, undefined, '', NAN, 0。先来看几个例子:

[] === []
NaN === NaN
NaN == NaN
0 == []
'' == []
'' == {}
[] == undefined
{} == []
null == undefined

以上这些判断结果是什么,大家能否一看就知道结果呢?笔者以前对==和===都只有大概的印象,相信大家也都知道,== 判断如果两边变量的类型不同,会将其先做类型转换再作判断,而 === 则不做类型转换,如果类型不同,就一定返回 false。但是笔者最近看到了一个题目,感觉很有意思,贴出来给大家看看:

var x = 1;
var obj = {
  valueOf: function(){ 
    x = 2; 
    return 0 
    }
  }
console.log(obj == 0, x)

恩,这段代码输出的结果是 true, 2,是不是不可思议?还有~

var x = 1;
var obj = {
  valueOf: function(){ 
    return {} 
  }, 
  toString: function(){ 
    return {}
  }
 }
 console.log(obj == 0)

这段代码直接抛出了异常: Uncaught TypeError: Cannot convert object to primitive value。

如果你和我一样觉得很奇怪,那就继续往下看吧~

=== 的规则

这个比较简单,我把规则罗列一下

  1. 如果类型不同,就不相等
  2. 如果两个都是数值,并且是同一个值,那么相等,例外的是,如果其中至少一个是NaN,那么不相等。(判断一个值是否是 NaN,只能用isNaN() 来判断)
  3. 如果两个都是字符串,每个位置的字符都一样,那么相等;否则不相等。
  4. 如果两个值都是true,或者都是false,那么相等。
  5. 如果两个值都引用同一个对象或函数,那么相等;否则不相等。
  6. 如果两个值都是null,或者都是undefined,那么相等。

这里不难发现,复合类型的数据(比如对象、数组、函数等)之间的比较不是比较他们的值是否相等,而是比较他们引用的对象是否一样,因此也不难明白,为什么 [] === [] 判断为false了。

比如:

JavaScript中三个等号和两个等号你了解多少

== 探究

看下 == 的规则

  1. 如果两个值类型相同,进行 === 比较。
  2. 如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:
  3. 如果一个是null、一个是undefined,那么相等。
  4. 如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
  5. 如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
  6. 如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。 js核心内置类,会尝试valueOf先于toString。例外的是Date,Date利用的是toString转换。非js核心的对象,会比较麻烦,有兴趣的同学可以研究一下
  7. 任何其他组合,都不相等。

看到这里,第六条,我们就可以明白,为什么上面的代码会输出意想不到的结果甚至抛出错误了。

再来看一题:

if (x == 10) 
  x += 5

根据上面的规则,试想一下,如果我们输入的x是字符串20,那么x的结果会变成什么样?没错,就是205,而往往这种情况我们的目的是想计算20+5的值。

综合上面的例子,不难看出,== 的比较看似会比较方便,比如 1 == '1' ,但是会埋下隐患,比如可能对类型做出错误的假设。因此大多数人建议我们少用== 而尽量使用 ===,事实上我也推荐如果明确知道类型,还是最好用===。

再举个简单的例子:团队协作中你肯定需要读别人的代码。而当你看到==时,要判断清楚作者的代码意图是确实需要转型,还是无所谓要不要转型只是随手写了,还是不应该转型但是写错了……所花费的脑力和时间比明确的===(加上可能需要的明确转型)要多得多。这样一想,===不要好太多。

明白了==的机制,那么判断这6个假值,就变得容易了。

简单看看几个例子,大家看看是真是假~

false == ''
false == []
0 == []
'' == []
[] == []
[] == {}
null == undefined
false == undefined

总结

可以用一张图来表达 == 返回true的几个假值:

JavaScript中三个等号和两个等号你了解多少

一、首先看双等号前后有没有NaN,如果存在NaN,一律返回false。

二、再看双等号前后有没有布尔,有布尔就将布尔转换为数字。(false是0,true是1)

三、接着看双等号前后有没有字符串, 有三种情况:

  1. 对方是对象,对象使用toString()或者valueOf()进行转换;
  2. 对方是数字,字符串转数字;
  3. 对方是字符串,直接比较;
  4. 其他返回false
  5. 如果是数字,对方是对象,对象取valueOf()或者toString()进行比较, 其他一律返回false
  6. null, undefined不会进行类型转换, 但它们俩相等

后记

我的建议是:如果你的的确确知道你在做什么(了解类型转换的结果),可以用==;否则还是用===吧。

在网上无意中看到的图,大家可以参考看看:

==号

JavaScript中三个等号和两个等号你了解多少

===号

JavaScript中三个等号和两个等号你了解多少

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 拖拽雏形中的一些问题(逐行分析代码,让你轻松了拖拽的原理)
Jan 23 Javascript
jscript读写二进制文件的方法
Apr 22 Javascript
ES6中非常实用的新特性介绍
Mar 10 Javascript
JavaScript解八皇后问题的方法总结
Jun 12 Javascript
JavaScript动态检验密码强度的实现方法
Nov 09 Javascript
Bootstrap输入框组件简单实现代码
Mar 06 Javascript
html+javascript+bootstrap实现层级多选框全层全选和多选功能
Mar 09 Javascript
Angular 4 指令快速入门教程
Jun 07 Javascript
Node.js利用js-xlsx处理Excel文件的方法详解
Jul 05 Javascript
EasyUI在Panel上动态添加LinkButton按钮
Aug 11 Javascript
vue实现固定位置显示功能
May 30 Javascript
基于Bootstrap和JQuery实现动态打开和关闭tab页的实例代码
Jun 10 jQuery
原生js实现简单的链式操作
Jul 04 #Javascript
详解用vue编写弹出框组件
Jul 04 #Javascript
使用vue构建一个上传图片表单
Jul 04 #Javascript
vue-resource 拦截器(interceptor)的使用详解
Jul 04 #Javascript
JavaScript在控件上添加倒计时功能的实现代码
Jul 04 #Javascript
JavaScript异步上传图片文件的实例代码
Jul 04 #Javascript
详解vue-router和vue-cli以及组件之间的传值
Jul 04 #Javascript
You might like
php+js iframe实现上传头像界面无跳转
2014/04/29 PHP
thinkPHP3.1验证码的简单实现方法
2016/04/22 PHP
值得分享的php+ajax实时聊天室
2016/07/20 PHP
PHP的反射机制实例详解
2017/03/29 PHP
jquery 学习笔记一
2010/04/07 Javascript
JS获取浏览器语言动态加载JS文件示例代码
2014/10/31 Javascript
js实现表单Radio切换效果的方法
2015/08/17 Javascript
20分钟轻松创建自己的Bootstrap站点
2016/05/12 Javascript
关于js函数解释(包括内嵌,对象等)
2016/11/20 Javascript
Nodejs 发送Post请求功能(发短信验证码例子)
2017/02/09 NodeJs
老生常谈combobox和combotree模糊查询
2017/04/17 Javascript
js与jQuery实现获取table中的数据并拼成json字符串操作示例
2018/07/12 jQuery
在vue中给列表中的奇数行添加class的实现方法
2018/09/05 Javascript
vue axios数据请求get、post方法及实例详解
2018/09/11 Javascript
react 兄弟组件如何调用对方的方法示例
2018/10/23 Javascript
详解Node.js中path模块的resolve()和join()方法的区别
2018/10/29 Javascript
Vue 自定义标签的src属性不能使用相对路径的解决
2019/09/17 Javascript
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
举例讲解如何在Python编程中进行迭代和遍历
2016/01/19 Python
Python的collections模块中namedtuple结构使用示例
2016/07/07 Python
pytorch 固定部分参数训练的方法
2019/08/17 Python
python用类实现文章敏感词的过滤方法示例
2019/10/27 Python
Python基础之字典常见操作经典实例详解
2020/02/26 Python
Python包和模块的分发详细介绍
2020/06/19 Python
html5 div布局与table布局详解
2016/11/16 HTML / CSS
趣味体育活动方案
2014/02/08 职场文书
暑期培训随笔感言
2014/03/10 职场文书
优秀团员自我评价范文
2014/04/23 职场文书
教研活动总结
2014/04/28 职场文书
党员批评与自我批评思想汇报
2014/10/08 职场文书
工会2014法制宣传日活动总结
2014/11/01 职场文书
工艺技术员岗位职责
2015/02/04 职场文书
单位实习介绍信
2015/05/05 职场文书
2016教师给学生的毕业寄语
2015/12/04 职场文书
详解Java线程池是如何重复利用空闲线程的
2021/06/26 Java/Android
浅谈Redis变慢的原因及排查方法
2022/06/21 Redis