Object.is 无法检测位运算溢出,因其仅实现 SameValue 语义,专用于区分 +0/-0 和让 NaN===NaN,对 Infinity、-Infinity、NaN 的判断与 === 完全一致;位运算会静默转为 32 位整数并截断,产生的是精度丢失和符号翻转,而非浮点溢出。

Object.is 不能检测位运算溢出风险,它对所有溢出值(如 Infinity、-Infinity、NaN)的判断行为与 === 完全一致。
为什么 Object.is 对溢出值无效
Object.is 的设计目标是实现 SameValue 语义,核心用途只有两个:精确区分 +0 和 -0,以及让 NaN === NaN 返回 true。它不关心数值是否溢出。
-
Object.is(1e309, Infinity)→false(因为1e309是Infinity,但Object.is不做类型或语义转换) -
Object.is(Infinity, Infinity)→true,但这只是因为它等价于===,不是“检测到了溢出” -
Object.is(-Infinity, -Infinity)→ 同样为true,但无法告诉你这个-Infinity是来自1 / -0还是-Number.MAX_VALUE * 2
位运算本身不会产生 Infinity 或 NaN
JavaScript 中的位运算符(&、|、^、~、<<、>>、>>>)会先将操作数强制转为 32 位有符号整数(即执行 ToInt32),这个过程会静默丢弃小数、模 2³²、并把超出范围的值映射进 [-2147483648, 2147483647] 区间。
-
2147483647 << 1→-2(不是Infinity,也不是报错) -
Math.pow(2, 53)经过| 0→0(高位全截断,无提示) - 所以“位运算溢出”实际是 精度丢失 + 符号翻转,而非浮点溢出,
Object.is完全不适用
真正该用什么检测位运算异常结果
位运算后若需验证结果是否符合业务预期,应基于语义检查,而不是依赖数值相等性工具:
- 若你期望结果是非负整数,用
value >= 0 && Number.isInteger(value) && (value | 0) === value - 若你依赖某一位为标志位(比如第 31 位表示开关),直接提取:
(value & 0x80000000) !== 0,比检查 “是否溢出” 更可靠 - 若输入本应是小正整数(如 ID、掩码),在位运算前就做范围守卫:
if (val < 0 || val > 0x7FFFFFFF) throw new RangeError('invalid bit operand') - 对关键位操作链(如多层
>>>后再&),保留原始输入快照,和输出做逻辑反推校验,例如:(input >>> shift) & mask === expected
真正容易被忽略的是:位运算的“溢出”从来不是运行时异常,而是输入失控 + 无校验导致的静默语义错误。与其纠结用哪个相等判断函数,不如在 >>> 前确认输入非负,在 << 前确认移位量 < 32,并在协议层约定好数据宽度边界。

















