JavaScript 提供三种不同的值比较运算:
===——严格相等(三个等号)==——宽松相等(两个等号)Object.is()
上述三个操作分别与 JavaScript 四个相等算法中的三个相对应:
- IsLooselyEqual (宽松相等比较):
== - IsStrictlyEqual (严格相等比较):
=== - SameValue (同值相等比较):
Object.is() - SameValueZero (零值相等比较):被许多内置运算使用
它们的区别如下:
- 在比较两个操作数时,双等号(
==)将执行类型转换,并且会按照 IEEE 754 标准对NaN、-0和+0进行特殊处理(故NaN != NaN,且-0 == +0); - 三等号(
===)做的比较与双等号相同(包括对NaN、-0和+0的特殊处理)但不进行类型转换;如果类型不同,则返回false; Object.is()既不进行类型转换,也不对NaN、-0和+0进行特殊处理(这使它和===在除了那些特殊数字值之外的情况具有相同的表现)。
宽松相等比较 ==
使用 == 执行宽松相等的行为如下:
- 如果操作数具有相同的类型,则按如下方式进行比较:
- 对象(Object):仅当两个操作数引用同一个对象时返回 true。
- 字符串(String):仅当两个操作数具有相同的字符且顺序相同时返回 true。
- 数字(Number):如果两个操作数的值相同,则返回 true。+0 和 -0 被视为相同的值。如果任何一个操作数是 NaN,返回 false;所以,NaN 永远不等于 NaN。
- 布尔值(Boolean):仅当操作数都为 true 或都为 false 时返回 true。
- 大整型(BigInt):仅当两个操作数的值相同时返回 true。
- 符号(Symbol):仅当两个操作数引用相同的符号时返回 true。
- 如果其中一个操作数为 null 或 undefined,另一个操作数也必须为 null 或 undefined 以返回 true。否则返回 false。
- 如果其中一个操作数是对象,另一个是原始值,则 将对象转换为原始值。
- 在这一步,两个操作数都被转换为原始值(字符串、数字、布尔值、符号和大整型中的一个)。剩余的转换将分情况完成。
- 如果是相同的类型,使用步骤 1 进行比较。
- 如果其中一个操作数是符号而另一个不是,返回 false。
- 如果其中一个操作数是布尔值而另一个不是,则将布尔值转换为数字:true 转换为 1,false 转换为 0。然后再次对两个操作数进行宽松比较。
- 数字与字符串:将字符串转换为数字。转换失败将导致 NaN,这将保证相等比较为 false。
- 数字与大整型:按数值进行比较。如果数字的值为 ±∞ 或 NaN,返回 false。
- 字符串与大整型:使用与 BigInt() 构造函数相同的算法将字符串转换为大整型数。如果转换失败,返回 false。
严格相等比较 ===
严格相等比较两个值是否相等。两个被比较的值在比较前都不进行隐式转换。如果两个被比较的值具有不同的类型,这两个值是不相等的。否则,如果两个被比较的值类型相同,值也相同,并且都不是 number 类型时,两个值相等。最后,如果两个值都是 number 类型,当两个都不是 NaN,并且数值相同,或是两个值分别为 +0 和 -0 时,两个值被认为是相等的。
同值相等比较 Object.is()
Object.is() 确定两个值是否为相同值。如果以下其中一项成立,则两个值相同:
- 都是 undefined
- 都是 null
- 都是 true 或者都是 false
- 都是长度相同、字符相同、顺序相同的字符串
- 都是相同的对象(意味着两个值都引用了内存中的同一对象)
- 都是 BigInt 且具有相同的数值
- 都是 symbol 且引用相同的 symbol 值
- 都是数字且
- 都是 +0
- 都是 -0
- 都是 NaN
- 都有相同的值,非零且都不是 NaN
零值相等比较
零值相等类似于严格相等和同值相等,但 NaN 和 NaN 被视为相等,+0 和 -0 被视为相等。
零值相等不作为 JavaScript API 公开,但可以通过自定义代码实现:
function sameValueZero(x, y) {
if (typeof x === "number" && typeof y === "number") {
// x 和 y 相等(可能是 -0 和 0)或它们都是 NaN
return x === y || (x !== x && y !== y);
}
return x === y;
}
严格相等、同值相等和零值相等的区别如下:
NaN === NaN
// false
-0 === +0
// true
Object.is(NaN, NaN)
// true
Object.is(-0, 0)
// false
sameValueZero(NaN, NaN)
// true
sameValueZero(-0, 0)
// true
参考
JavaScript 中的相等性判断
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness