==和===到底有什么区别

转载自 https://baijiahao.baidu.com/s?id=1572551881586789
很多时候我们会对某个语言的某个特性争论不休,通常都只是因为我们不知道它是怎么实现的。其实解决这个疑惑的最好的方法,就是弄清楚 == 和 === 内部的实现机制。

例如 Google v8 就是开源的,只要看看里面的代码,就能知道到底是怎么一回事了。但是我相信绝大多数人都是没有这个耐心的——我知道大家都在忙着挣钱养家——好吧,那咱就不看 Google v8 了,看看 ECMA-262 吧,里面已经把实现算法描述得很清楚了,只要看懂了下面的内容,以后就再也不会有此类疑问了。

一、严格相等运算符 === 的实现

=== 被称为 Strict Equals Operator,假设有表达式 a === b,则它的实际运算过程如下

计算出表达式 a 的结果,并存入 lref 变量

将 GetValue(lref) 的结果存入 lval 变量

计算出表达式 b 的结果,并存入 rref 变量

将 GetValue(rref) 的结果存入 rval 变量

执行 Strict Equality Comparison 算法判断 rval === lval 并将结果直接返回

这里的 Strict Equality Comparison 算法很关键,假设要计算的是 x === y,则过程如下

1. 如果 Type(x) 和 Type(y) 不同,返回 false

2. 如果 Type(x) 为 Undefined,返回 true

3. 如果 Type(x) 为 Null,返回 true

4. 如果 Type(x) 为 Number,则进入下面的判断逻辑

	4.1. 如果 x 为 NaN,返回 false
	
	4.2. 如果 y 为 NaN,返回 false
	
	4.3. 如果 x 的数字值和 y 相等,返回 true
	
	4.4. 如果 x 是 +0 且 y 是 -0,返回 true
	
	4.5. 如果 x 是 -0 且 y 是 +0,返回 ture
	
	4.6. 返回 false

5. 如果 Type(x) 为 String,则当且仅当 x 与 y 的字符序列完全相同(长度相等,每个位置上的字符相同)时返回 true,否则返回 false

6. 如果 Type(x) 为 Boolean,则若 x 与 y 同为 true 或同为 false 时返回 true,否则返回 false

7. 如果 x 和 y 引用的是同一个对象,返回 true,否则返回 false

二、相等运算符 == 的实现

好了,当你明白了 === 的实现之后,我们再来看看 == 的实现,比较一下他们有何不同?

== 被称为 Equals Operator (注意看没有 Strict 了),假设有表达式 a == b,则它的实际运算过程如下

执行 Abstract Equality Comparison 算法判断 rval == lval 并将结果直接返回

注意,其中的前 4 个步骤是和 === 完全相同的。唯独 5 不同。对于 === 来说,调用的是 Strict Equality Comparison 算法,但是 == 则调用的是 Abstract Equality Comparison 算法。虽然仅一词之差,但是却有质的不同,我们下面就来看看到底它是怎么实现的

假设要计算的是 x == y,Abstract Equality Comparison 计算的过程如下(很冗长,但是每个步骤都很简单)

1. 如果 Type(x) 和 Type(y) 相同,则

	1.1. 如果 Type(x) 为 Undefined,返回 true
	
	1.2. 如果 Type(x) 为 Null,返回 true
	
	1.3. 如果 Type(x) 为 Number,则
	
	1.3.1. 如果 x 是 NaN,返回 false
	
	1.3.2. 如果 y 是 NaN,返回 false
	
	1.3.3. 如果 x 的数值与 y 相同,返回 true
	
	1.3.4. 如果 x 是 +0 且 y 是 -0,返回 true
	
	1.3.5. 如果 x 是 -0 且 y 是 +0,返回 true
	
	1.3.6. 返回 false
	
	1.4. 如果 Type(x) 为 String,则当且仅当 x 与 y 的字符序列完全相同(长度相等,每个位置上的字符相同)时返回 true,否则返回 false
	
	1.5. 如果 Type(x) 为 Boolean,则若 x 与 y 同为 true 或同为 false 时返回 true,否则返回 false
	
	1.6. 如果 x 和 y 引用的是同一个对象,返回 true,否则返回 false

2. 如果 x 是 null 且 y 是 undefined,返回 true

3. 如果 x 是 undefined 且 y 是 null,返回 ture

4. 如果 Type(x) 为 Number 且 Type(y) 为 String,以 x == ToNumber(y) 的比较结果作为返回

5. 如果 Type(x) 为 String 且 Type(y) 为 Number,以 ToNumber(x) == y 的比较结果作为返回值

6. 如果 Type(x) 为 Boolean,以 ToNumber(x) == y 的比较结果作为返回值

7. 如果 Type(y) 为 Boolean,以 x == ToNumber(y) 的比较结果作为返回值

8. 如果 Type(x) 为 String 或 Number 且 Type(y) 为 Object,以 x == ToPrimitive(y) 的比较结果作为返回值

9. 如果 Type(x) 为 Object 且 Type(y) 为 String 或 Number,以 ToPrimitive(x) == y 的比较结果作为返回值

10. 返回 false

三、总结

从上面的算法流程可以看出,a === b 是最简单的。如果 a 和 b 的类型不同,那么一定会返回 false。而 a == b 则要灵活得多。JavaScript 会尝试调整 a 和 b 的类型,例如若 a 为字符串 b 为数字,则将字符串先转化为数字再与 b 比较,等等。这在很多时候简化了程序员的代码量。

一些程序员害怕 == 而提倡使用 === 的根本原因是,他们不知道在 == 的内部具体发生了什么。而这就导致误用和出错。

很多人认为,当我们不了解一个 feature 的时候,我们就不用它就行了。这也许是一种习惯性逻辑。但尴尬的是你不用这个 feature 没问题,别人却可能还是会用。为了能读懂别人的代码,我们又必须实际上搞清楚这内在的逻辑。所以最终还是得付出这方面的学习成本。

这真是让人尴尬的一件事。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值