如何利用 Object.is 区分 +0 与 -0 并正确处理 NaN 的相等判断
Object.is:不止于“严格相等”的精确比较工具

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
说起 Ja vaScript 里的相等判断,===(严格相等)通常是我们的首选。但有没有一种情况,连 === 都觉得不够“严格”?答案是肯定的。这就引出了 Object.is 这个 ES6 引入的“裁判”。它和 === 很像,但在两个关键点上采取了更精确的立场:它能区分 +0 和 -0,并且判定 NaN 等于 NaN。这背后遵循的是 IEEE 754 浮点数标准的位模式比较逻辑,而非抽象相等算法。当然,它并不深入比较对象内容,因此在日常的相等判断中,=== 依然是更通用、更高效的选择。
Object.is 能否区分 +0 和 -0
能,而且这是它与 === 最核心的差异之一。执行 Object.is(+0, -0) 会得到 false,而 +0 === -0 则返回 true。从数学角度看,零的符号不同确实有意义;Object.is 严格遵从 IEEE 754 规则,比较两者的位模式——+0 和 -0 的符号位相反,因此被判为不相等。
那么,什么时候该用上这个特性呢?
- 需要感知零的符号时:比如在坐标系计算中区分方向归零,或在某些金融场景里辨别“正向归零”与“负向归零”,这时就必须使用
Object.is,===会掩盖这个差异。 - 检查是否为 -0:直接写
Object.is(x, -0),比传统的1 / x === -Infinity这种技巧更直观、更安全。 - 注意一个小细节:
Object.is(-0, 0)同样返回false,因为代码中的字面量0等价于+0。
Object.is 对 NaN 的处理为什么可靠
另一个关键区别在于对 NaN 的处理。Object.is(NaN, NaN) 稳稳地返回 true,而 NaN === NaN 则永远是 false。原因在于,Object.is 不经过抽象相等算法,而是直接比较两个值的内部表示。在 IEEE 754 标准中,所有 NaN 都被视为“同一种不可比较的值”,Object.is 的规范则明确规定了它们彼此相等。
这带来了更精准的实践方案:
- 校验意外产生的 NaN:当需要检测像
Math.sqrt(-1)或0 / 0这类运算的结果时,使用Object.is(result, NaN)比isNaN()或Number.isNaN()更精准,后两者可能存在类型转换的干扰。 - 告别 Hack 写法:可以避免使用
result !== result这种可读性差、且在特定调试或优化环境下可能不可靠的技巧来判断NaN。 - 需要明确的是:
Object.is只对真正的NaN值生效,字符串"NaN"不会被误判。
什么时候不该用 Object.is 替代 ===
是不是所有情况都应该用更“严格”的 Object.is 呢?并非如此。在很多日常场景中,它的行为反而显得“过于严格”了。
使用前,不妨先看看这几个常见的注意点:
- 不进行深度比较:对于对象或数组,
Object.is和===一样,只比较引用是否相同,返回false。别指望它能替代_.isEqual或JSON.stringify这类深度比较方案。 - 增加不必要的认知负担:对于字符串、数字、布尔值等基本类型,绝大多数业务逻辑用
===已经完全足够且语义清晰。引入Object.is反而可能让代码意图变得模糊。 - 细微的性能差异:由于多了一层对符号位和
NaN的特殊判断,Object.is的性能通常略慢于===(在 V8 引擎中大约慢 10%~15%)。在超高频的循环中,这点差异值得权衡。 - 环境兼容性:虽然现代环境(ES6+)都已支持,但如果代码需要运行在极老的浏览器(如 IE)中,则必须添加 polyfill,或者降级为
===并手动补充对零符号和NaN的判断。
一个实用的工具函数封装建议
直接使用 Object.is 有时会显得意图不够明确,也容易遗漏边界情况。一个不错的实践是根据具体需求,将其封装成语义更清晰的工具函数:
const isNegativeZero = (val) => Object.is(val, -0);
const isNaNValue = (val) => Object.is(val, NaN);
const isSameZero = (a, b) => {
if (!Object.is(a, b)) return false;
// 此时 a 和 b 已相等,但若都是 0,还需确认符号一致
return !Object.is(a, +0) || !Object.is(b, -0) || Object.is(a, b);
};
注意看最后一个 isSameZero 函数,它的逻辑看似有点绕,却恰恰揭示了一个关键点:Object.is 的真正价值,并不在于提供一个“更通用”的相等判断,而在于**让你能够精确控制对 +0/-0 和 NaN 的判定时机**。用错了场景,它不会让你的代码更简洁;但用对了地方,它能帮你堵住那些由浮点数特性引发的、极其隐蔽的逻辑漏洞。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
Less如何提升CSS维护性_使用参数化Mixin实现灵活组件
Less参数化Mixin:如何写出既灵活又可控的样式代码? Less参数化Mixin怎么写才不重复造轮子 开门见山,参数化Mixin的核心目标不是炫技,而是解决一个实际问题:把那些“可能会变”的样式值抽离出来。这样一来,样式规则只需定义一次,修改时就能全局生效,维护效率自然就上去了。关键在于,你得准
Vue 中的 Patch 过程是怎么工作的?从 VNode 到真实 DOM 的转化全指南
Vue 中的 Patch 过程是怎么工作的?从 VNode 到真实 DOM 的转化全指南 Patch 的核心目标:高效更新 DOM 简单来说,Vue 的 Patch 过程干的就是一件“聪明事”:它拿着新旧两份虚拟节点(VNode)清单,只去更新真实 DOM 里真正变了的那部分,而不是不管三七二十一,
CSS如何实现移动端加载占位骨架屏_利用CSS渐变色与动画效果
CSS如何实现移动端加载占位骨架屏:利用渐变色与动画效果 先明确一个核心概念:一个真正好用的骨架屏,本质上不是图片,而是用CSS背景渐变“画”出来的容器轮廓。关键在于,如何让background-image精准覆盖真实内容区域,同时巧妙地利用透明间隙来模拟文字或头像的留白。这听起来简单,但实际操作时
CSS如何实现侧边栏推拽切换_利用CSS动画平滑过渡布局
侧边栏推拽用 transform: translateX() 更流畅,避免 left margin-left 触发重排;初始隐藏用 translateX(-100%),配合 ease-out 或自定义 cubic-bezier 过渡更自然;移动端需谨慎 preventDefault() 并启用 -w
Ionic 7 中在 Tab 内实现页面内导航的完整教程
Ionic 7 中在 Tab 内实现页面内导航的完整教程 本文详解如何在 Ionic 7(Vanilla JS)中为单个 Tab 配置独立的嵌套路由系统,解决 ion-router 在 ion-tab 内无法正常跳转的问题,并提供可运行的结构化实现方案。 如果你正在用 Ionic 7 的纯 Ja v
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

