JavaScript的==通过抽象相等算法执行隐式类型转换实现跨类型比较,而===跳过转换、类型不同直接返回false。

JavaScript 中的 ==(抽象相等)和 ===(严格相等)对不同类型对象的比较行为不同,但真正“支持与不同类型对象比较且返回合理结果”的机制,核心在于 抽象相等算法(Abstract Equality Comparison) 的隐式类型转换规则。它不是“智能判断语义合理性”,而是按明确步骤进行类型协调后比较。
抽象相等(==)如何处理跨类型比较
当使用 == 比较两个不同类型的操作数时,JavaScript 会按规范执行以下关键步骤:
- 若一方为
null,另一方为undefined,直接返回 true(这是唯一一对“特殊相等”) - 若一方为数字,另一方为字符串,将字符串转为数字再比较(如
"42" == 42→42 == 42→ true) - 若一方为布尔值,先转为数字:
false → 0,true → 1(如true == 1→1 == 1→ true) - 若一方为对象(含数组、日期、普通对象等),另一方为原始值(字符串/数字/布尔),则先调用对象的
[Symbol.toPrimitive]('default'),若未定义,则尝试valueOf(),再失败则调用toString(),将其转为原始值后再继续比较
常见对象类型的比较表现
理解这些典型场景有助于预判结果:
-
[] == false→true:空数组valueOf()返回自身(非原始值),toString()返回空字符串"";"" == false→0 == 0→ true -
[0] == false→true:数组转字符串为"0",再转数字为0,0 == 0→ true -
new Date(0) == 0→true:日期对象valueOf()返回时间戳数字0 -
{} == "[object Object]"→false:对象转字符串是"[object Object]",但这是字符串比较,不等于其自身字符串字面量(除非显式 toString)
为什么严格相等(===)更可靠
=== 完全跳过类型转换,只要类型不同就直接返回 false:
-
"42" === 42→ false(字符串 vs 数字) -
true === 1→ false(布尔 vs 数字) -
[] === []→ false(两个不同对象引用) - 只有类型相同且值相等(或引用同一对象)才为 true
自定义对象如何控制比较逻辑
若希望对象参与有意义的相等判断,应主动实现可预测的行为:
- 重写
valueOf()或toString(),让抽象相等有明确原始值映射(但不推荐依赖 ==) - 更现代的方式:使用
[Symbol.isEqual](非标准,需自行约定)或提供.equals(other)方法 - 对复杂对象,推荐用
Object.is()(比 === 更严谨,能区分+0/-0和NaN)或结构化深比较库(如 Lodash 的isEqual)










