Object.is 能区分 +0 和 -0 是因为其按 IEEE 754 位模式严格比较,故 Object.is(+0, -0) 返回 false;同时它使 Object.is(NaN, NaN) 为 true,更符合相等直觉。

Object.is 为什么能区分 +0 和 -0
JavaScript 中 === 把 +0 和 -0 当作相等,但数学上它们符号不同;Object.is 按 IEEE 754 规范严格比较位模式,因此 Object.is(+0, -0) 返回 false。这是它和 === 最直观的差异点。
实操建议:
- 当你要检测一个值是否“真正为负零”(比如浮点运算结果、坐标轴方向判断),别用
val === -0—— 它在+0上也会意外通过;改用Object.is(val, -0) - 注意:
1 / -0得-Infinity,而1 / +0是+Infinity,所以区分符号零有时直接影响后续计算逻辑 - 不要依赖
Math.sign(-0) === -0来判断——Math.sign(-0)返回-0,但Math.sign(+0)也返回+0,两者仍可能被误判相等
Object.is 对 NaN 的处理比 === 更合理
=== 规定任何值(包括 NaN)都不等于 NaN,导致 NaN === NaN 为 false;而 Object.is(NaN, NaN) 明确返回 true,符合“同一个 NaN 值应视为相等”的直觉。
实操建议:
- 做数组去重或 Set 插入时,若元素可能含
NaN,new Set([NaN, NaN])实际保留两个NaN(因为 Set 内部用===判重),但用Object.is自定义去重逻辑就能合并 - 写工具函数如
deepEqual时,遇到NaN必须优先用Object.is(a, b)判断,否则NaN字段永远不匹配 - 注意:
Number.isNaN()只判断是否为NaN,不解决相等性问题;isNaN()还会强制转换,更不可靠
Object.is 不是万能替代 === 的方案
Object.is 在多数场景下行为和 === 一致,但它对 +0/-0 和 NaN 的特殊处理,反而会在某些地方打破预期。
实操建议:
- 不要全局替换
===为Object.is—— 比如状态对比中,你可能希望+0和-0被视为相同初始值,这时===更符合业务语义 -
Object.is不处理类型转换,这点和===一样;但它的字符串比较仍是字面量级,Object.is("0", 0)仍为false - 性能上,
Object.is略慢于===(V8 中约 10% 差距),高频循环里慎用,尤其在非关键路径外没必要强求
实际用例:安全判断浮点计算结果是否为负零
比如你在做图形变换或物理模拟,需要根据 y 坐标是否为 -0 来决定镜像方向,而用户输入可能导致 y = -0.0 * x 这类表达式。
错误写法:if (y === -0) { /* 镜像 */ } —— 当 y 是 +0 时不会进分支,但当 y 是 -0 时看似能进,可一旦上游用了 Math.atan2(0, -1) 这类返回 -0 的函数,就容易漏判。
正确写法:
if (Object.is(y, -0)) {
// 确保只在 y 是负零时执行
}这个判断绕过了符号位被忽略的风险,也避免了用 y 这种反直觉的组合判断。
真正容易被忽略的是:很多开发者知道 Object.is 能判 NaN,却忘了它对 0 的符号敏感性——而这恰恰是浮点数值稳定性中最隐蔽的坑之一。

















