菜单

相等比较

相关源文件

本文档详细介绍了 JavaScript 的相等性比较运算符(=====Object.is()),并解释了它们如何处理不同类型的值。理解这些运算符对于编写可预测且能根据您的具体需求正确评估值是否相等的代码至关重要。

有关类型强制转换的通用信息,请参阅 类型强制转换系统。有关关系比较(<> 等)的详细信息,请参阅 原始类型行为

相等性运算符概述

JavaScript 提供了三种不同的机制来比较值的相等性

运算符/方法姓名类型检查特殊情况用例
==宽松/强制相等强制不同类型null == undefined 视为 true当类型差异可接受时
===严格相等要求相同类型NaN-0/+0 进行特殊处理最常用、默认选择
Object.is()相同值相等要求相同类型NaN-0/+0 最准确当需要精确相等时

来源:types-grammar/ch4.md256-351 types-grammar/ch2.md348-403

来源:types-grammar/ch4.md256-351 types-grammar/ch2.md348-403

严格相等 (===)

严格相等运算符(===)在不执行强制转换的情况下比较值和类型。它遵循以下步骤:

  1. 如果操作数的类型不同,则返回 false
  2. 如果两个值类型相同,则直接比较它们的值
  3. 对于数字,应用 NaN-0/+0 的特殊规则

尽管其名称暗示最严格的相等形式,=== 仍有两个值得注意的例外:

  • NaN === NaN 返回 false,即使它们是相同的值
  • 0 === -0 返回 true,即使它们在技术上是不同的值

来源:types-grammar/ch4.md294-326 types-grammar/ch2.md355-363

宽松相等 (==)

宽松相等运算符(==)在操作数类型不同时会执行类型强制转换后再比较值。这遵循一个特定的算法:

宽松相等的主要行为

  1. 如果类型相同,则其行为类似于 ===
  2. nullundefined 之间强制相等(但与其他任何值都不相等)
  3. 比较字符串和数字时,字符串会被转换为数字
  4. 布尔值会被转换为数字(false 为 0,true 为 1)
  5. 对象通过 ToPrimitive() 转换为原始类型

来源:types-grammar/ch4.md328-349 types-grammar/ch2.md372-388

Same-Value 相等 (Object.is)

Object.is() 方法提供了最精确的数学相等性比较,处理了 === 未能正确处理的边界情况。

Object.is() 基于抽象的 SameValue() 操作,它比 === 使用的 IsStrictlyEqual() 操作更严格。

来源:types-grammar/ch4.md258-292 types-grammar/ch2.md392-402

不同类型值的相等性

原始值

每种原始类型都有其独特的相等性行为。

类型相等性行为
字符串逐字符比较
数字数值相等,对 NaN-0 进行特殊处理
布尔值简单值比较(truefalse
null仅与 null 相等(或在 == 下与 undefined 相等)
未定义仅与 undefined 相等(或在 == 下与 null 相等)
symbol每个 symbol 都是唯一的,仅与自身相等
bigint数值比较

来源:types-grammar/ch1.md42-125 types-grammar/ch2.md348-403

对象值

对象通过引用进行比较,而不是通过内容。

在使用宽松相等(==)时,对象会先转换为原始类型再进行比较,这可能导致意外的结果。

来源:types-grammar/ch3.md29-62 types-grammar/ch4.md339-345

特殊的相等性情况

null 和 undefined

nullundefined 值在相等性比较中具有特殊的关系。

这种行为通常用于检查“nullish”值。

来源:types-grammar/ch1.md94-158 types-grammar/ch4.md332-333

NaN 处理

NaN 代表一个无效的数字,并且具有独特的相等性行为。

来源:types-grammar/ch4.md308-325 types-grammar/ch2.md355-363

零值 (0, -0)

JavaScript 区分正零和负零,但在相等性比较中并非总是如此。

来源:types-grammar/ch4.md308-325 types-grammar/ch2.md355-363

相等性背后的抽象操作

JavaScript 规范定义了几个为相等性比较提供动力的抽象操作。

这些抽象操作定义了相等性在不同上下文中的精确行为,处理 NaN-0undefined/null 等边界情况。

来源:types-grammar/ch4.md256-326

选择正确的相等性运算符

当决定使用哪个相等性运算符时:

  1. 默认使用 === - 它避免了意外的类型强制转换,是最可预测的。
  2. 当有意允许类型差异时使用 == - 例如,当使用 x == null 检查 nullish 值时。
  3. 对于边界情况使用 Object.is() - 当您特别需要对 NaN-0 进行精确比较时。

来源:types-grammar/ch4.md347-349 types-grammar/ch2.md399-402

常见陷阱

警惕这些常见的与相等性相关的注意事项:

  1. 数组相等性 - 数组是按引用比较,而不是按内容比较。

  2. 对象相等性 - 对象是按引用比较,而不是按结构比较。

  3. 类型强制转换的意外行为 - 意外的隐式转换。

  4. Unicode 字符串比较 - 规范化可能会影响相等性。

来源: types-grammar/ch1.md443-459 types-grammar/ch2.md348-389 types-grammar/ch4.md339-345

总结

JavaScript 提供了三种相等比较机制,每种都有独特的行为

  1. 松散相等 (==) - 允许类型转换,在类型差异可接受时很有用
  2. 严格相等 (===) - 要求类型相同,通常因其可预测性而更受欢迎
  3. 值相等 (Object.is()) - 数学上精确,能正确处理边缘情况

理解这些运算符之间的差异对于编写可靠的 JavaScript 代码至关重要。在大多数情况下,=== 是最安全的选择,但特定用例可能需要其他比较方法。

来源:types-grammar/ch4.md256-351 types-grammar/ch2.md348-403