Object.is 和 === 的区别是什么?
面试速答(30 秒版 TL;DR)
- 大多数情况下:
Object.is(a, b)与a === b结果相同。 - 两个关键差异(必须背):
NaN:NaN === NaN是false,但Object.is(NaN, NaN)是true。+0/-0:+0 === -0是true,但Object.is(+0, -0)是false。
- 口径:
===是“严格相等(Strict Equality)”,Object.is更接近“同值相等(SameValue)”。
为什么会有差异?
可以把它理解成“规范层面的相等算法不同”:
===:对NaN特判为不相等;不区分+0/-0。Object.is:把NaN视为等于自身;区分+0/-0。
这两个差异本质上都来自 IEEE 754 浮点数的一些边界行为。
一眼看懂的例子
// 1) NaN
NaN === NaN; // false
Object.is(NaN, NaN); // true
// 2) +0 / -0
0 === -0; // true
Object.is(0, -0); // false
// 3) 其他大多数情况
Object.is("a", "a") === ("a" === "a"); // true
Object.is({}, {}) === ({} === {}); // true,都为 false(引用不同)
什么时候用 Object.is 更合适?
- 你需要把
NaN当作“等于自身”的值来比较(例如一些数值计算结果的稳定性判断)。 - 你需要区分
+0和-0(极少见,但可能出现在数值分析/底层库中)。 - 你在写一些通用工具函数,希望在边界上更“精确”。
业务代码里绝大多数比较仍然用 === 即可,语义更直观。
典型题 & 标准答法
Q1:那 Object.is 是不是可以完全替代 ===?
不建议这么说。面试回答可以是:
- “绝大多数情况下两者一致,我默认用
===,只有在需要NaN自反性或区分+0/-0时用Object.is。”
Q2:Map / Set / includes 用的是哪种相等?
常见口述点(记住结论即可):
Array.prototype.includes会把NaN当作可匹配到(这点和indexOf不同)。Map/Set的 key 匹配也能匹配到NaN。
你可以用下面的小例子记忆验证:
[NaN].indexOf(NaN); // -1
[NaN].includes(NaN); // true
const s = new Set([NaN]);
s.has(NaN); // true
易错点/坑(速记)
Object.is不是“深相等”,对象比较依然是引用比较:Object.is({}, {})仍为false。- 不要把
Object.is和==混在一起讲:==涉及类型转换,是另一套话题。