在ES2015 (ES6)中,比较操作有四种:
- Loose equality: ==
- Strict equality: ===
- SameValue: Object.is(1, “1”)
- 集合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时不一样,其它结果都时一样的。
- -0 === 0,结果true;Object.is(-0, 0),结果false。
- 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。
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 |