Object.is 是唯一能可靠区分 +0 和 -0 的方法,因 +0 === -0 为 true,但二者在除法、JSON 序列化等场景行为不同,易致统计偏差;需用 Object.is 归一化或精确判断负零,并在测试中显式覆盖。

Object.is 是唯一能可靠区分 +0 和 -0 的 JavaScript 原生方法,这对浮点数统计场景至关重要——因为 +0 === -0 为 true,但它们在某些数学操作(如除法、JSON 序列化、部分聚合逻辑)中行为不同,可能引发隐性偏差。
为什么“负零”会在统计中悄悄出问题
负零通常由带符号的浮点运算产生,例如:-1 / Infinity、-0.1 + 0.1(受精度影响有时得 -0)、或显式写 -0。它和正零在大多数比较中无法区分:
-
+0 === -0→true -
Object.is(+0, -0)→false✅ -
1 / +0→Infinity,而1 / -0→-Infinity -
JSON.stringify({x: -0})→"{"x":0}"(丢失符号),导致反序列化后无法还原
在数据聚合前主动归一化“零值”
若统计逻辑依赖键名(如用 Map 或对象记录频次)、或后续要转为 JSON 传输,应统一将 -0 视为 +0 处理:
- 对原始数组/数据流中的每个数值,用
Object.is(x, -0)判断并修正:Object.is(val, -0) ? 0 : val - 若使用
reduce累加平均值或方差,先过滤或转换输入值,避免-0进入中间状态 - 示例:处理传感器数据流时,在进入
sum += value前插入校验
用 Object.is 替代 == / === 做关键分支判断
当统计逻辑需根据“是否为负零”做特殊处理(如标记异常方向、分离双向流量),必须用 Object.is:
- 错误写法:
if (delta === -0) { /* 不会触发 */ } - 正确写法:
if (Object.is(delta, -0)) { /* 精确捕获负零 */ } - 注意:
Math.sign(-0)返回-0,但Math.sign(+0)返回0,也可辅助判断;不过Object.is更直接、无类型转换风险
在单元测试中显式覆盖负零边界情况
很多统计函数的测试用例只覆盖 0,漏掉 -0。建议在测试数据集中加入:
- 输入含
-0的数组(如[1, -0, -0, 2]),验证去重、分组、求和结果是否符合预期 - 检查输出 JSON 是否意外抹去符号(可对比
JSON.stringify前后值的Object.is结果) - 对返回对象的字段做
Object.is(actual.x, expected.x)断言,而非仅用deepEqual










