JavaScript中==会触发隐式类型转换而===不会;==按抽象相等算法转换类型后比较,===要求类型和值均相同;推荐用===以避免隐蔽bug,仅val == null可作为检查null/undefined的安全简写。
JavaScript 中的类型转换主要分两种:显式转换(你主动调用 Number()、String()、Boolean() 等)和隐式转换(运算符或比较时自动发生)。而 == 和 === 的核心区别就在于是否触发隐式类型转换——== 会,=== 不会。
当使用 == 比较两个值时,如果类型不同,JS 引擎会按固定步骤尝试转换其中一方(或双方),再比较。这个过程由“抽象相等算法”定义,关键逻辑如下:
null 或 undefined,仅当两者同为 null 或同为 undefined 时返回 true;null == undefined 是 true,但它们都不等于其他任何值(包括 0、false、空字符串)"123" == 123 → 123 == 123 → true)fa
lse → 0,true → 1(所以 true == 1 为 true,false == 0 也为 true)valueOf(),若结果不是原始值,再调用 toString(),直到得到原始值再继续比较(例如 [0] == false → [0].toString() → "0" → "0" == false → "0" == 0 → 0 == 0 → true)=== 完全跳过类型转换。它要求:类型相同 且 值相等。只要类型不同,直接返回 false。
0 === false → false(number vs boolean)"1" === 1 → false(string vs number)null === undefined → false(类型不同)NaN === NaN → false(这是唯一一个自己不等于自己的情况,=== 也不例外)0 === -0 → true(ES6 规定二者类型值均相同)这些看似反直觉的结果,其实都严格遵循上面的转换规则:
[] == false → true:空数组 toString() 得 "",再转数字为 0,0 == false → true
[0] == false → true:如前所述,[0].toString() → "0" → Number("0") → 0 → 0 == false
{} == true → false:对象先 valueOf()(返回自身,非原始值),再 toString() → "[object Object]",转数字为 NaN,NaN == true → NaN == 1 → false
"0" == false → true:字符串转数字得 0,0 == false
因为 == 的转换逻辑复杂、隐蔽,依赖上下文,容易导致意外行为和难以调试的 bug。现代代码规范(如 ESLint 的 eqeqeq 规则)默认禁止 ==,除非明确需要宽松比较(比如检查 null || undefined,可用 val == null 作为简写)。
=== 可预测、可读性高、性能略优(省去转换开销)Number(str) === 42 或 String(num) === "42"
null 或 undefined,val == null 是安全且被广泛接受的简写(等价于 val === null || val === undefined)