关于对“===”和“==”的思考

前提:偶然逛知乎看见关于对“===”和“==”比较的提问,觉得蛮有意思的,让我这种小白明白这么叫图样图森破。所以来写篇博客纪念下;


知乎原帖:

Javascript 中 == 和 === 区别是什么?
JavaScript 中应该用 “==” 还是 “===”?


我们都该知道

~ 严格相等运算符“===”在比较的时候,首先计算操作数的值,然后比较这两个值,比较的过程中没有任何类型转换。

~ 相等运算符“==”在比较的过程中存在类型转换。

那么

1.相等运算符“==”进行类型转换会不会改变原来的变量?会不会产生其他的影响?
2.严格相等运算符“===”既然不会进行类型转换是不是就要比相等运算符“==”更推荐使用呢?
……………………………………………..
a.首先进行类型转换是不会改变原来的变量的,在变量赋值时内存会存储值的类型;做双等号比较操作时,会先做临时类型转换再做比较,内存中存储的值还是原来的不会改变。

b.来自知乎:“== 是能产生副作用的,如果你覆写某个对象的 valueOf/toString 的话。== 的隐式类型变换正是调用了这两个方法,如果在覆盖的方法里写了带有副作用的代码,确实也会导致 == 带来副作用。

例子:

Array.prototype.valueOf = function() {
  this[0]++;
  return this;
}
var x = [1, 2, 3];
x == 0;
console.log(x);   // [2, 2, 3]

c.而关于推荐使用的这个问题,我在知乎得到的答案,总结而来是这个意思,“==”的实现虽然比“===”的实现复杂,切可能会带来作用(b),但是如果愿意去了解的话,使用并不会成为问题。(所以如果你恰巧也要这样的思虑,那就让我们一起好好学习吧)


来自ECMAScript Lanuage Specification 9.13 9.16

The Abstract Equality Comparison Algorithm(“==”算法)

相等运算符 == 的实现

好了,当你明白了 === 的实现之后,我们再来看看 == 的实现,比较一下他们有何不同?
== 被称为 Equals Operator (注意看没有 Strict 了),假设有表达式 a == b,则它的实际运算过程如下

计算出表达式 a 的结果,并存入 lref 变量
将 GetValue(lref) 的结果存入 lval 变量
计算出表达式 b 的结果,并存入 rref 变量
将 GetValue(rref) 的结果存入 rval 变量
执行 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

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

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

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

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

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

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

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

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

  9. 返回 false。

NOTE 4:字符串的比较,使用一个简单的等式测试序列的代码单元值。有没有尝试使用更复杂的语义定义的字符或字符串的平等和排序顺序在Unicode规范定义。因此,规范字符串值相等,根据Unicode标准测试不平等。实际上这个算法假定字符串已经正常的形式。


The Strict Equality Comparison Algorithm(“===”算法)

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

=== 被称为 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

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

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

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


以上可以看出”==”的实现确实比“===”更为复杂


待完善!

参考:
edit fiddle :http://jsfiddle.net/26Lf0a0L/
ECMAScript :http://www.ecma-international.org/ecma-262/5.1/
http://javascript.ruanyifeng.com/grammar/operator.html#toc6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值