-0会悄悄破坏业务逻辑,因其符号携带语义(如金融支出归零、坐标负向趋近),但===判断返回true掩盖差异,导致分支错误、日志误判、API不一致;唯一可靠检测方式是Object.is(x, -0)。

为什么 -0 会悄悄破坏业务逻辑
浮点数计算中出现 -0 本身不报错,但它的符号在某些场景下携带语义:比如金融系统里“-0.00”可能表示「支出归零」,而 +0 表示「收入归零」;坐标系中 -0 可能代表「从负方向趋近原点」。用 === 判断时,-0 === 0 返回 true,直接掩盖差异,导致分支走错、日志误判、甚至 API 返回值不一致。
检测 -0 的三种可靠方式(只推荐一种)
别用 String(x) === '-0' —— 在某些旧引擎或严格模式下不可靠;也别依赖 1 / x === -Infinity —— 若 x 是非数字(如 null 或空字符串),会得到 -Infinity 假阳性。
-
唯一推荐:
Object.is(x, -0),它直接比对 IEEE 754 位模式,安全、直观、无副作用 -
Object.is(x, +0)同理成立,但注意字面量0就是+0,所以Object.is(x, 0)实际等价于Object.is(x, +0) - 若需批量校验(如数组每项是否为
-0),必须用Object.is配合.some()或.every(),不能替换为===
在数值去重与状态对比中漏掉 -0 的后果
用 Set 去重时,new Set([0, -0]) 实际只存一个值,因为 Set 内部用的是 SameValueZero 算法(和 === 一致);同理,React 的 useMemo 或 Redux 的浅比较若只靠 ===,-0 和 +0 会被当作相同输入,跳过本该触发的重新计算。
- 手动实现带
-0感知的去重函数,必须用Object.is(seenItem, item)替代seenItem === item - 在状态 diff 工具中(如自定义
shouldUpdate),把-0当作独立状态值处理,否则坐标归零动画方向可能反转 - API 响应体若含
-0,JSON 序列化后变成0,前后端联调时容易误以为“数据没变”,实则语义已丢失
最容易被忽略的边界点
不是所有产生 -0 的操作都显眼:比如 Math.atan2(-0, 1) 返回 -0,-123 * 0 也是 -0,甚至 -+0 这种写法都会产出 -0。一旦这些值进入后续计算链(如作为除数、传给 Math.sign() 或参与 toFixed()),结果就可能偏离预期。
真正难调试的,是那些只在特定输入组合下才偶然产出 -0 的数学函数调用 —— 它们不会抛错,也不会警告,只是让下游逻辑静默拐弯。

















