33 个 JavaScript 核心概念系列(四): == 与 ===
原文地址:落明的博客,转载请注明出处!
一、前言
作为一个程序员,我想大家在第一次看到 a = b
的语句时一定是懵逼的。后来才知道 =
在编程语言中是用来赋值的,而不是用来判断两个值是否相等。
那该怎么判断两个值是否相等呢?在 C 或 java 中,是使用 ==
来进行比较,而 JavaScript 就有意思了,除了使用 ==
, 还加了 ===
。
二、区别与选择
它们有什么区别?
具体的区别就一句话:
==
在比较时允许进行强制类型转换,而===
不允许。很多人都担心
==
做的事情多一些会不会影响比较的速度,说实话,会的,但影响是微秒级别的,完全可以忽略不计。不难看出,
==
像是===
的一种更深入的扩展,因此,满足===
的值一定满足==
,反之则不成立。该如何选择使用它们?
很多人会建议你坚持使用
===
而不使用==
, 我认为这是不明智的,有些时候,比如说处理后端返回的数据时,你无法保证对方传来的值到你进行比较的时候还是预期的那样,此时我觉得完全在可以适当的使用==
来进行兼容。总的来说,当你真的确定进行比较的值是类型相同的,那就使用
===
,否则,除了几种特殊情况,使用==
并没有什么问题 。
三、===
的比较规则
基本类型值的比较
===
的比较规则很简单,对于非对象类型的值,先判断两边的操作数是否是同一类型,如果是,则进行比较,否则,直接返回false
。但有两个例外情况:
NaN === NaN
和+0 === -0
。// 不同类型 '12' === 12; // false 'a' === true; // false null === '12' // false null === undefined; // false// 同类型 1 === 1; // true 'a' === 'a'; // true false === false; // true null === null; // true//特殊情况 NaN === NaN; // false +0 === -0 // true 复制代码
引用类型值的比较
对于包含引用类型值的比较,仍然会先判断两边的数据类型,如果只有一个是引用类型值,则直接返回
false
,如果两边均是引用类型值,则会比较他们的引用地址是否一致。const a = {m: 'string',n: 12 }; const b = {m: 'string',n: 12 }; const c = 12;a === b; // false a === c ; // falseconst d = a; a === d; // true 复制代码
四、==
的比较规则
一开始说过了,在使用 ==
进行比较时,运行对两边的操作数进行强制类型转换,那么问题来了,什么情况下会进行转换?不同类型的转换规则又是怎样?
在 MDN
中有这样一张表,用来展示不同类型值进行 ==
判断时的转换规则。
乍一看可能会觉得很乱,但仍然是可以分几种情况来概括这些情况。
在具体分析之前,建议先阅读上一篇文章 显式 (名义) 与 隐式 (鸭子)类型转换 ,因为上图中你能看到有诸如 isFalsy()
、ToNumber()
、ToString()
、ToPrimitive
等抽象方法,使用它们只是为了让大家知道强制转换的方向和结果,而这些也都是上一篇文章讲到的内容。
Undefined
和Null
与其它类型值的比较我们看前两行和前两列可以发现:它们只和自身及对方相等,与其他类型值比较均返回
false
。 ....这个大概就是传说中的「黑风双煞」吧!大家可能会看到
Object
有一个isFalse()
方法,这个方法是用来判断参数值是否是假值,这个时候大家可能会有疑问了,对象不是都是真值吗?没错,
document.all
就是一个假值对象,虽然已经被新的 JavaScript 标准废弃,但你或许会在老的项目中看到它,记住就好。由于这俩值的特殊性,后面我们说“其他类型”值的时候是排除这俩类型的。
Number
类型值与其他类型值比较除了上面的黑风双煞,
Number
算是相等比较时的大哥,谁想和它比较,就得先转成Number
类型。Boolean
类型值与其他类型值比较既然有大哥,肯定得有小弟,而
Boolean
类型值则一马当先,以身作则,将大哥的原则贯彻到底,堪称模范小弟!其他类型值想和
Boolean
值做比较,Boolean
值摇身一变将自己转成了Number
类型,哎,你说,别人能怎么办?!无论别人怎么说,
Boolean
只想做一只安静的舔狗,无怨无悔,一生一世。Object
类型值与其他类型值比较Object
作为 JavaScript 中最会伪装自己的一种类型,在比较之前谁也摸不透它们的真实身份。也正因为此,它们的日子过得不尽相同。在进行比较时,JavaScript 国王会通过
toPrimitive()
方法来揭开他们的真面目,最终你会发现,它们的真实身份可能是任意的一种基本类型。因此,在最终比较时,它们也将以真实身份与其他类型值比较。
String
类型值与其他类型值比较对于
String
类型值来说,在进行比较时的日子并不好过,毕竟,黑风双煞惹不起,黑社会说话也得听,唯一能让它感受到生活希望的,就是在与Object
这个变色龙进行比较的时候了。只有
Object
在toPrimitive()
后转为字符串的时候它们可以以字符串的规则进行比较,否则,它们就要面临黑风双煞或是黑社会。
五、==
正确的使用方法
github 上有位大神总结了下面这张图:
我们可以将此当做一份参考。
其实在实际的使用过程中,只要我们避免一些特殊的情况,==
的使用还是安全的。
下面就是七种所谓的特殊情况。
"0" == false; // true -- 晕!
false == 0; // true -- 晕!
false == ""; // true -- 晕!
false == []; // true -- 晕!
"" == 0; // true -- 晕!
"" == []; // true -- 晕!
0 == []; // true -- 晕!
复制代码
如何避免?两个原则:
- 如果两边的值中有 true 或者 false,千万不要使用 ==。
- 如果两边的值中有 []、"" 或者 0,尽量不要使用 ==。
六、最后
检验大家成果的时候到了,
- 仔细想想上面七种特殊情况的产生原因。
- 思考下面这些值的比较结果。
[] == ![]; // ?
2 == [2]; // ?
'' == [null] // ?Number.prototype.valueOf = function() {return 3;
};
new Number( 2 ) == 3; // ?复制代码
33 个 JavaScript 核心概念系列(四): == 与 ===相关推荐
- 33 个 JavaScript 核心概念系列(三): 显式 (名义) 与 隐式 (鸭子)类型转换
原文地址:落明的博客 一. 前言 说实话,JavaScript 的类型转换是个相当头疼的问题,无论是对于初学者还是有经验的老司机.它的难处并不在于概念多难理解,而是情况多且杂,看似相同的情况结果却又出 ...
- javascript 核心概念(1)-数据类型
语法 (1)到现在为止,大多数浏览器也还是支持到ECMAScript 第三版的标准. 核心概念就是一个语言的基本工作原理,涉及语法,操作符,数据类型. (2)javascript的一切--变量,函数名 ...
- JavaScript 核心概念之作用域和闭包
相信大家已经阅读了很多关于作用域和闭包文章,我也一样.作用域和闭包是 JavaScript 中的关键概念之一.当我阅读了<高性能的JavaScript>这本书后,我才完全理解这两个概念.所 ...
- Spring框架(二) 底层架构核心概念解析-四万字你值得一看
本篇文章将对Spring底层的一些概念做一些简单的分析 , 也是为了方便后续在阅读源码的时候更加的方便 BeanDefintion BeanDefintion是一个接口 , 它表示一个Bean的定义 ...
- [云原生专题-33]:K8S - 核心概念 - 服务Service管理、服务发现、负载均衡
作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...
- 学习 JavaScript (四)核心概念:操作符
JavaScript 的核心概念主要由语法.变量.数据类型.操作符.语句.函数组成,前面三个上一篇文章已经讲解完了.后面三个内容超级多,这篇文章主要讲解的是操作符. 操作符 什么叫做操作符? 这是一种 ...
- webpack的四个核心概念
从 webpack v4.0.0 开始,可以不用引入一个配置文件.然而,webpack 仍然还是高度可配置的.在开始前你需要先理解四个核心概念: 入口(entry) 输出(output) loader ...
- Maven——Maven核心概念——史上最烂系列
Maven 是目前最流行的自动化构建工具,对于生产环境下多框架.多模块整合开发有重要作用.Maven 是一款在大型项目开发过程中不可或缺的重要工具.(自己粗略写了一个SSM项目之后,回顾头来看这个,会 ...
- Maven学习总结(四)——Maven核心概念
2019独角兽企业重金招聘Python工程师标准>>> Maven学习总结(四)--Maven核心概念 一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平 ...
最新文章
- python插件做nagios发报警邮件二
- 每天一个linux命令(20):find命令之exec
- oracle 10g视频教程
- [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)
- 作为软件工程师,你必须知道的20个常识
- 37条常用Linux Shell命令组合
- matlab画置信区间图,matlab绘制带置信区间的双y轴图形 | 学步园
- bagging and boosting
- python数据分析师工作内容_数据分析师日常工作是什么?
- Arduino 极速入门系列 - 光控灯(3) - 光敏电阻、与电阻分压那些事
- 二次优化大招(由泰勒公式推出最值条件)
- remote addr 取到内网ip_内网穿透工具frp
- Linux系统7个运行级别图文详解
- linux输出文件没有找到,Linux环境下标准输入、输出、错误信息详解
- 【点阵液晶编程连载五】液晶驱动代码的移植
- OSO.EXE病毒专杀工具
- 201809-1 卖菜
- php 字母加1,PHP语法(1)
- PhpStorm 配置 Git 教程
- LABVIEW 学习-温度采集系统
热门文章
- 全面介绍Windows内存管理机制及C++内存分配实例(三):虚拟内存
- python-matplotlib学习(1)
- python中的map、filter、reduce函数
- Win7下Maven的安装与配置
- vfork()系统调用
- 3D Game Programming with directx 11 习题答案 8.3
- JS中格式化数据保留两位小数
- 轻量级Ajax解决方案:Anthem.NET初探
- 只有22%的人做对了这道数据分析题,你来试试吗?
- 辞旧迎新,胖了几斤?数据告诉你,这种东西你就不该吃