JavaScript 四种相等算法详解:同值、同值零、非严格与严格相等

作者:资源驿站时间:2026-10-25 15:02:54浏览:596

本文详解 JavaScript 中的四种相等算法:同值、同值零、非严格相等(==)与严格相等(===)。重点解析非严格相等的隐式类型转换规则、严格相等对 NaN 和 ±0 的处理差异,以及 Object.is 和 includes 等方法的底层逻辑,帮助开发者避免隐式转换陷阱,选择正确的比较方式。

前言

在 JavaScript 中判断两个值是否相等,看似基础却暗藏玄机。JavaScript 规范中定义了四种不同的相等算法,若不清楚它们的具体区别,容易在开发中遇到难以排查的问题。本文旨在深入解析这四种算法,帮助读者建立正确的比较观念。

ECMAScript 作为 JavaScript 的核心规范,明确定义了四种相等算法,具体分类如下图所示:

前言

上述图片展示了四种算法的中文名称。前端开发者通常对“严格相等”和“非严格相等”较为熟悉,但对于“同值”和“同值零”可能较为陌生。接下来将逐一介绍这四种算法的具体行为与应用场景。

  • 同值
  • 同值零
  • 非严格相等
  • 严格相等

非严格相等

非严格相等使用双等号(==)进行比较,其核心语义是“语义相等”,不要求操作数类型一致。在比较前,JavaScript 引擎会尝试将两个操作数的类型转换为一致,然后再进行值比较。代码示例如下:

1 == 1; // true
1 == '1'; // true 类型不同,不影响比较结果

非严格相等的类型转换规则极为复杂,难以凭记忆掌握。社区中有开发者将其整理为可视化图表,如下图所示,直观展示了各种类型间的转换路径:

前言

为了便于记忆非对象类型的转换逻辑,可以总结为以下三条核心规则:

  • Undefined 类型仅与 Null 类型相等
  • 当与 Number 类型比较时,另一个值会自动转换为 Number 类型
  • 当与 Boolean 类型比较时,另一个值会先转换为 Number 类型

若比较值为对象,JavaScript 会调用其内部的 ToPrimitive 方法将其转换为原始值。开发者可以通过定义 Symbol.toPrimitive 符号来自定义转换行为。需要注意的是,在非严格相等判断中,Symbol.toPrimitive 接收的 hint 参数始终为

const obj = {
  [Symbol.toPrimitive](hint) {
    console.log(hint);
    if (hint == 'number') {
      return 1;
    }
    if (hint == 'string') {
      return 'yan';
    }
    return true;
  },
};

console.log(obj == 1); // obj 返回 true
console.log(obj == '1'); // obj 返回 true
console.log(obj == true); // obj 返回 true

非严格相等虽然通过隐式自动转换简化了部分场景(如 Number 与 String 的转换,便于处理表单或 URL 参数),但其带来的隐式转换问题往往多于便利。

由于隐式转换规则复杂且难以预测,主流观点已不推荐广泛使用非严格相等。作者建议,仅在明确需要判断 undefined 和 null 的场景下,才使用非严格相等。

严格相等

严格相等是另一种比较算法,其与非严格相等的核心区别在于不进行任何类型转换。如果两个操作数的类型不一致,直接返回 false。严格相等对应 === 操作符,因使用三个等号,也被称为“三等”或“全等”。代码示例如下:

1 === 1; // true
1 === '1'; // false 类型不同,影响比较结果

不同类型值的判断规则如下,与非严格相等相比,严格相等的行为更符合直觉,避免了意外的类型转换。

前言

严格相等解决了非严格相等中隐式转换带来的隐患,但也失去了隐式转换的便利。对于类型可能不一致的场景(例如从表单获取的值均为字符串),保险的做法是在比较前进行手动类型转换。代码示例如下:

1 === Number('1'); // true 手动类型转换,类型防御

虽然严格相等在绝大多数情况下是正确的选择,但仍存在例外情况,主要涉及 NaN 和正负零(+0/-0)的处理。

Number 类型有一个特殊值 NaN,用于表示计算错误。常见于非 Number 类型与 Number 类型运算时,结果可能为 NaN,这是从表单或接口获取数据时容易遇到的问题。代码示例如下所示:

const a = 0 / 0; // NaN
const b = 'a' / 1;
const c = undefined + 1; // NaN

在严格相等中,NaN 不等于自身,即 (x !== x) 是唯一成立的情况。若需判断 NaN,可使用 isNaN 函数。ECMAScript 2015 引入了更语义化的 Number.isNaN,它不会对参数进行类型转换,建议优先使用,但需注意浏览器兼容性问题。判断 NaN 的代码示例如下:

NaN === NaN; // false

isNaN(NaN); // true
Number.isNaN(NaN); // true

isNaN('aaa'); // true 自动转换类型 'aaa'转换为Number为NaN
Number.isNaN('aaa'); // false 不进行转换,类型不为Number,直接返回false

严格相等的另一个例外是无法区分 +0 和 -0,代码示例如下。在某些数学计算场景中,区分正负零具有语义重要性。

+0 === -0; // true

JavaScript 中许多系统函数使用严格相等,如数组的 indexOf、lastIndexOf 以及 switch-case 语句。需要注意的是,这些方法无法正确识别 NaN,代码示例如下:

[NaN].indexOf(NaN); // -1 数组中其实存在NaN
[NaN].lastIndexOf(NaN); // -1

同值零

同值零(SameValueZero)是另一种相等算法,名称源自规范直译。其功能与严格相等基本一致,唯一区别在于对 NaN 的处理:同值零认为 NaN 等于 NaN。这在判断 NaN 是否存在于集合中的语义下更为合理。

ECMAScript 2016 引入的 Array.prototype.includes 方法使用同值零算法。此外,Map 的键去重和 Set 的值去重也采用此算法。代码示例如下:

[NaN].incdudes(NaN); // true 注意和indexOf的区别,incdudes的语义更合理

new Set([NaN, NaN]); // [NaN] set中只会有个一个NaN,如果 NaN !== NaN的话,应该是[NaN, NaN]

new Map([
  [NaN, 1],
  [NaN, 2],
]); // {NaN => 2} 如果 NaN !== NaN的话,应该是 {NaN => 1, NaN => 2}

同值

同值(SameValue)是最后一种相等算法,与同值零类似,但认为 +0 不等于 -0。ECMAScript 2015 引入的 Object.is 方法使用同值算法。代码示例如下:

Object.is(NaN, NaN); // true
Object.is(+0, -0); // false 📢 注意这里

同值算法适用于确定两个值在“任何情况下功能上是否相同”的场景,使用频率较低。例如,Object.defineProperty 使用同值算法确认键是否存在:将存在的只读属性值 -0 修改为 +0 时会报错,而设置为同样的 -0 则正常执行。代码示例如下:

function test() {
  'use strict'; // 需要开启严格模式
  var a = {};

  Object.defineProperty(a, 'a1', {
    value: -0,
    writable: false,
    configurable: false,
    enumerable: false,
  });

  Object.defineProperty(a, 'a1', {
    value: -0,
  }); // 正常执行

  Object.defineProperty(a, 'a1', {
    value: 0,
  }); // Uncaught TypeError: Cannot redefine property: a1
}
test();

在判断数组中是否存在特定值的场景中,若需区分 +0 和 -0,可使用 ECMAScript 2015 引入的 Array.prototype.find 方法,并自行控制判断逻辑。代码示例如下:

[0].includes(-0); // 不能区分-0
[0].find((val) => Object.is(val, -0)); // 能区分+0和-0

总结

最后,通过下表对比四种算法的区别:

 隐式转换NaN 和 NaN+0 和 -0
非严格相等(==)是falsetrue
严格相等(===)否falsetrue
同值零(includes 等)否truetrue
同值(Object.is)否truefalse

到此这篇关于 JavaScript 判断两个值相等的方法详解的文章就介绍到这了,更多相关 JavaScript 判断值相等内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章