object.is() 是更数学意义上精确的等值判断,能区分 +0 与 -0、使 nan 与自身相等,适用于底层计算、序列化及 nan 稳定比对场景,但不支持对象/数组深度比较。
object.is() 解决的是 === 在两个特殊值上“不够严”的问题:+0 与 -0 被视为相等,nan 与自身不相等。它不是“更通用”的等号,而是“更数学意义上精确”的等值判断,适用于需要区分正负零、或需稳定判定 nan 的场景。
区分 +0 和 -0 的真实需求
大多数业务逻辑中 +0 === -0 是合理的(比如温度、余额归零),但某些底层操作必须区分:
- 数值符号参与后续计算(如除法:
1 / -0得-Infinity,而1 / +0得+Infinity) - 序列化/反序列化时保留原始符号信息(如 WebGL 坐标、金融系统中的方向性零值)
- 实现符合 IEEE 754 标准的数学库或调试工具
此时用 Object.is(+0, -0) 返回 false,比 === 更可靠;也可配合 1 / x 或 Object.is(x, -0) 显式检测负零。
让 NaN 稳定自比较成立
NaN === NaN 永远为 false,这在做数组去重、对象属性值比对、缓存键匹配时会出问题。例如:
const arr = [NaN, 1, NaN]; console.log([...new Set(arr)]); // [NaN, 1, NaN] —— Set 用 SameValueZero,不识别 NaN 相等
若手动实现去重逻辑,用 Object.is(a, b) 就能正确识别两个 NaN 相等:
- 遍历数组时,用
!seen.some(v => Object.is(v, current))判断是否已存在 - 自定义 Map 键比较、React 中
useMemo依赖项深度比对(需搭配结构遍历) - 避免误用
arr.indexOf(NaN)(永远返回 -1),改用arr.findIndex(v => Object.is(v, NaN))
注意:它不解决对象/数组的深度相等
Object.is({a:1}, {a:1}) 仍为 false,因为它只做**同一性+特殊值修正**判断,不递归比较内容。若需深度等值校验:
- 简单结构可用
JSON.stringify(a) === JSON.stringify(b)(有局限:顺序敏感、忽略 undefined/function、循环引用报错) - 生产环境推荐
lodash.isEqual()或fast-deep-equal - 自定义逻辑中,把
Object.is作为叶子节点(原始值)的最终比较手段,嵌套结构则递归调用
与 SameValueZero 的关系
JavaScript 内部很多算法(如 Array.prototype.includes、Set 查找、Map 键匹配)实际使用的是 SameValueZero 算法:它把 +0 和 -0 视为相等,其余同 Object.is。所以:
-
[0, -0].includes(+0)→true(SameValueZero) -
Object.is(+0, -0)→false(SameValue) - 需要严格数学一致性时选
Object.is;需要与内置方法行为一致时,理解 SameValueZero 即可










