“用 ===,别用 ==!” 然而,即使是看似完美的 ===,在某些极端场景下也会暴露出它的问题。
现在,是时候了解一个新的成员了,它并非要彻底取代 ===,而是为了填补其留下的空白,让“相等”这个概念在 JavaScript 中变得更加精确和符合直觉。
严格相等 ===
=== 规定:不仅值要相等,类型也必须相同,它从不进行类型转换。
'1' === 1; // false,类型不同(string vs number)
true === 1; // false,类型不同(boolean vs number)
null === undefined; // false,类型不同
在 99% 的场景下,=== 都表现得非常出色,它清晰、可靠、符合预期。然而,它在处理两个 JavaScript 中的“特殊公民”时,却显得有些力不从心。
=== 的两个问题
1.NaN 的自我否定
NaN 是一个非常特殊的值,它代表一个“非数字”的结果,根据 IEEE 754 标准,NaN 不等于任何值,包括它自己。
NaN === NaN; // false
这在数学上是合理的,但在编程中却很麻烦。比如,我们想在一个数组中查找 NaN,indexOf 或 includes 方法(在 ES6 之前)会因为这个特性而失效。
2.被抹平的正负零
在 JavaScript 中,数字 0 有两种表示:+0 (或 0) 和 -0。它们在数学运算和某些底层应用(如图形学)中具有不同的意义。然而,=== 认为它们是完全相等的。
-0 === +0; // true
对于绝大多数应用来说,这并无大碍,但对于需要高精度数学计算的场景,这种模糊处理可能会导致问题。
更精确的同值相等
为了解决 === 的这两个问题,ES 为我们引入了一个新的 API:Object.is(),它被定义为同值相等。
Object.is() 的行为逻辑可以简单概括为:
在绝大多数情况下,Object.is(a, b) 的结果与 a === b 相同。唯一的区别在于它如何处理 NaN 和 -0
让我们看看 Object.is() 是如何完美解决上述问题的:
1.NaN 等于 NaN
Object.is() 认为 NaN 和 NaN 是相等的。
Object.is(NaN, NaN); // true
这使得检查一个值是否为 NaN 变得更加直观(尽管我们仍然有 Number.isNaN() 这个更专业的工具)。
2.区分 +0 和 -0
Object.is() 能够清晰地分辨出正零和负零。
Object.is(-0, +0); // false
Object.is(0, -0); // false
Object.is(0, 0); // true
目前,JavaScript 内部的许多新特性已经在使用 Object.is() 的“同值相等”逻辑了,比如 Map 的键匹配和 Set 的值存储。
Object.is() 并不是 === 的替代品,而是一个强大的补充,它提供了一种在 JavaScript 中更严格精确的相等性定义。
我们的开发实践可以这样总结:默认使用 ===:它快速、可靠,并且能处理绝大多数情况;在需要处理 NaN 或 -0 的特殊场景下,使用 Object.is()。
阅读原文:https://mp.weixin.qq.com/s/o6m_97IP5M7S1lZd333kMA
该文章在 2025/11/26 10:37:47 编辑过