相等性判断

js/sameness2026-08-24 19:46:25

JavaScript 提供三种不同的值比较运算:

  • ===——严格相等(三个等号)
  • ==——宽松相等(两个等号)
  • Object.is()

上述三个操作分别与 JavaScript 四个相等算法中的三个相对应:

  • IsLooselyEqual (宽松相等比较):==
  • IsStrictlyEqual (严格相等比较):===
  • SameValue (同值相等比较):Object.is()
  • SameValueZero (零值相等比较):被许多内置运算使用

它们的区别如下:

  • 在比较两个操作数时,双等号(==)将执行类型转换,并且会按照 IEEE 754 标准对 NaN、-0 和 +0 进行特殊处理(故 NaN != NaN,且 -0 == +0);
  • 三等号(===)做的比较与双等号相同(包括对 NaN、-0 和 +0 的特殊处理)但不进行类型转换;如果类型不同,则返回 false;
  • Object.is() 既不进行类型转换,也不对 NaN、-0 和 +0 进行特殊处理(这使它和 === 在除了那些特殊数字值之外的情况具有相同的表现)。

宽松相等比较 ==

使用 == 执行宽松相等的行为如下:

  1. 如果操作数具有相同的类型,则按如下方式进行比较:
    • 对象(Object):仅当两个操作数引用同一个对象时返回 true。
    • 字符串(String):仅当两个操作数具有相同的字符且顺序相同时返回 true。
    • 数字(Number):如果两个操作数的值相同,则返回 true。+0 和 -0 被视为相同的值。如果任何一个操作数是 NaN,返回 false;所以,NaN 永远不等于 NaN。
    • 布尔值(Boolean):仅当操作数都为 true 或都为 false 时返回 true。
    • 大整型(BigInt):仅当两个操作数的值相同时返回 true。
    • 符号(Symbol):仅当两个操作数引用相同的符号时返回 true。
  2. 如果其中一个操作数为 null 或 undefined,另一个操作数也必须为 null 或 undefined 以返回 true。否则返回 false。
  3. 如果其中一个操作数是对象,另一个是原始值,则 将对象转换为原始值。
  4. 在这一步,两个操作数都被转换为原始值(字符串、数字、布尔值、符号和大整型中的一个)。剩余的转换将分情况完成。
    • 如果是相同的类型,使用步骤 1 进行比较。
    • 如果其中一个操作数是符号而另一个不是,返回 false。
    • 如果其中一个操作数是布尔值而另一个不是,则将布尔值转换为数字:true 转换为 1,false 转换为 0。然后再次对两个操作数进行宽松比较。
    • 数字与字符串:将字符串转换为数字。转换失败将导致 NaN,这将保证相等比较为 false。
    • 数字与大整型:按数值进行比较。如果数字的值为 ±∞ 或 NaN,返回 false。
    • 字符串与大整型:使用与 BigInt() 构造函数相同的算法将字符串转换为大整型数。如果转换失败,返回 false。

严格相等比较 ===

严格相等比较两个值是否相等。两个被比较的值在比较前都不进行隐式转换。如果两个被比较的值具有不同的类型,这两个值是不相等的。否则,如果两个被比较的值类型相同,值也相同,并且都不是 number 类型时,两个值相等。最后,如果两个值都是 number 类型,当两个都不是 NaN,并且数值相同,或是两个值分别为 +0 和 -0 时,两个值被认为是相等的。

同值相等比较 Object.is()

Object.is() 确定两个值是否为相同值。如果以下其中一项成立,则两个值相同:

  • 都是 undefined
  • 都是 null
  • 都是 true 或者都是 false
  • 都是长度相同、字符相同、顺序相同的字符串
  • 都是相同的对象(意味着两个值都引用了内存中的同一对象)
  • 都是 BigInt 且具有相同的数值
  • 都是 symbol 且引用相同的 symbol 值
  • 都是数字且
    • 都是 +0
    • 都是 -0
    • 都是 NaN
    • 都有相同的值,非零且都不是 NaN

零值相等比较

零值相等类似于严格相等和同值相等,但 NaN 和 NaN 被视为相等,+0 和 -0 被视为相等。

零值相等不作为 JavaScript API 公开,但可以通过自定义代码实现:

function sameValueZero(x, y) {
  if (typeof x === "number" && typeof y === "number") {
    // x 和 y 相等(可能是 -0 和 0)或它们都是 NaN
    return x === y || (x !== x && y !== y);
  }
  return x === y;
}

严格相等、同值相等和零值相等的区别如下:

NaN === NaN
// false

-0 === +0
// true
Object.is(NaN, NaN)
// true

Object.is(-0, 0)
// false
sameValueZero(NaN, NaN)
// true

sameValueZero(-0, 0)
// true

参考

JavaScript 中的相等性判断
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness

本页目录