javascript相等比较

By | 6月 16, 2020

在ES2015 (ES6)中,比较操作有四种:

  1. Loose equality:  ==
  2. Strict equality: ===
  3. SameValue: Object.is(1, “1”)
  4. 集合includes方法: Array, ArrayBuffer, Set, Map。判断是否包含元素。

1. Loose equality:  ==

A == B, 会把A转换成B类型或把B转换成A类型,然后执行strict equality (===)比较。比较规则:

Operand B
Undefined Null Number String Boolean Object
Operand A Undefined true true false false false false
Null true true false false false false
Number false false A === B A === ToNumber(B) A === ToNumber(B) A == ToPrimitive(B)
String false false ToNumber(A) === B A === B ToNumber(A) === ToNumber(B) A == ToPrimitive(B)
Boolean false false ToNumber(A) === B ToNumber(A) === ToNumber(B) A === B ToNumber(A) == ToPrimitive(B)
Object false false ToPrimitive(A) == B ToPrimitive(A) == B ToPrimitive(A) == ToNumber(B) A === B

不推荐使用loose equality (==),==最终还是用===比较。但是===没有类型转换,所以效率更高。

2. Strict equality: ===

如果数据类型不一样,返回false;类型一样再比较是否相等。通常情况下,我们都应该使用===,比较结果符合人的理解。-0 === +0,结果是true。但是需要注意strict equality认为NaN和任何值都不相等,NaN === NaN返回false。javascript内部有个isNaN方法,用于判断value是否为NaN。isNaN(NaN)返回true。

3. SameValue: Object.is(1, “1”)

它和Strict equality (===)在比较正负0和NaN时不一样,其它结果都时一样的。

  1. -0 === 0,结果true;Object.is(-0, 0),结果false。
  2. NaN === NaN,结果false;Object.is(NaN, NaN),结果True。

Object.is()用的比较少,尽量用===。如果要比较NaN,使用isNaN()方法。除非真的需要区分正负0,才需要使用Object.is()方法。

4. 集合includes方法

判断Array,ArrayBuffer, Set, Map是否包含某个元素,返回结果符合人的理解,只需要注意下正负0情况。

let nums: number[] = [ 1, -0, NaN ];
nums.includes(0); // True
nums.includes(NaN); // True

5. 总结

为了方便记忆,我们可以建立一个理解模型。

  • strict equality (===) 是比较基础。
  • loose equality (==) 是 strict equality (===) 的扩展,==先转换成相同类型,再执行===比较。
  • Object.is()弥补了===的不足,区分正负0,且可以比较NaN。但是适用地方不多,建议能用===就用===。
  • includes()方法,判断集合是否包含元素,不区分正负0。
Sameness Comparisons
x y == === Object.is includes
undefined undefined true true true true
null null true true true true
true true true true true true
false false true true true true
'foo' 'foo' true true true true
0 0 true true true true
+0 -0 true true false true
+0 0 true true true true
-0 0 true true false true
0 false true false false false
"" false true false false false
"" 0 true false false false
'0' 0 true false false false
'17' 17 true false false false
[1, 2] '1,2' true false false false
new String('foo') 'foo' true false false false
null undefined true false false false
null false false false false false
undefined false false false false false
{ foo: 'bar' } { foo: 'bar' } false false false false
new String('foo') new String('foo') false false false false
0 null false false false false
0 NaN false false false false
'foo' NaN false false false false
NaN NaN false false true true

6. Reference