本文深入解析 JavaScript 中的四种相等性:严格相等、非严格相等、同值相等与零值相等。重点对比 ===、== 与 Object.is 的行为差异,特别是 NaN、+0/-0 及隐式类型转换的特殊规则,帮助开发者避免常见陷阱。
在 JavaScript 中,相等性判断是一个基础但容易引发误解的概念。理解不同类型的比较规则对于编写稳健的代码至关重要。
1、严格相等(===)
严格相等(===)本质上判断一个值是否与自身相等,比较前不进行任何隐式类型转换。当两个值的类型相同且值也相同时,它们被视为全等,但 Number 类型除外。对于 Number 类型,需要特别注意 NaN 和零的处理:NaN 与 NaN 不相等(即使使用 ===),而 +0 与 -0 是全等的。除此之外,只要类型和值一致,即判定为全等。
NaN === NaN //false
+0 === -0 // true
undefined === undefined //true
null === null //true
undefined === null //false
({}) === {} //false
3 === '3' //false
3 === 3 //true
true === true //true
false === 0 //false2、非严格相等(抽象相等)(==)
非严格相等(==)用于判断两个值是否相等。在比较前,JavaScript 引擎会尝试将两个值转换为相同的类型,遵循特定的类型转换规则。转换完成后,其比较逻辑与严格相等(===)的规则基本一致。
| 比较规则(A/B) | undefined | null | Number | String | Boolean | Object |
|---|---|---|---|---|---|---|
| undefined | true | true | false | false | false | false |
| null | true | true | false | false | false | false |
| Number | false | false | A === B | toNumber(B)===A | toNumber(B)===A | toPrimetive(B) == A |
| String | false | false | toNumber(A)===B | A===B | toNumber(A)===toNumber(B) | toPrimetive(B) == A |
| Boolean | false | false | toNumber(A)===B | toNumber(A)===toNumber(B) | A===B | toPrimetive(B) == toNumber(A) |
| Object | false | false | toPrimitive(A) == B | toPrimitive(A) == B | toPrimetive(A) == toNumber(B) | A===B |
null == undefined // true
null == 0 // false
null == '' // false
null == 'null' //false
null == false // false
null == [] //false
null == {} //false
null == NaN //false
undefined == 0 //false
undefined == '' //false
undefined == 'undefined' //false
undefined == false //false
undefined == [] //false
undefined == {} //false
undefined == NaN //false
'' == 0 //true
'' == false //true
'' == [] //true
'' == {} // false
0 == false // true
0 == [] // true
0 == {} // false
true == '1' //true
true == 'true' //false
true == 1 // true
true == [] //false
false == [] //true
true == {} //false
([]) == [] //false
({}) == {} //false
3 == '3' //true
NaN == NaN // false
+0 == -0 // true总结上述规律可知:undefined 和 null 在抽象相等比较中视为相等。然而,当 undefined 或 null 与其他类型进行相等比较时,不进行隐式类型转换,因此它们与任何其他类型的值都不相等。所有对象与 undefined 和 null 均不相等,但存在特例,例如 document.all == undefined 和 document.all == null 的比较结果均为 true。
通过对比严格相等和非严格相等,可以发现严格相等的结果更具可预测性,且无需进行耗时的类型转换,因此执行效率通常更高。
3、同值相等
同值相等用于判断两个值是否代表同一个值,通过 Object.is() 方法进行判断,这是 ES6 引入的新特性。它类似于严格相等,不会对传入的两个参数进行隐式类型转换,但在处理 +0、-0 以及 NaN 时与严格相等存在显著差异。
- 两者均为 undefined
- 两者均为 null
- 两个相同的字符串
- 两者均为 true 或者均为 false
- 引用值相同的两个对象
- 两者均为 NaN
- 两者均为不为 NaN 且不为 0 的值相同的数字
- 两者均为 +0 或者均为 -0
Object.is(NaN, NaN) //true
Object.is(NaN, 0 / 0) // true
Object.is(+0, -0) // false
Object.is(+0, +0) //true
Object.is(undefined, undefined) //true
Object.is(null, null) //true
Object.is(undefined, null) //false
Object.is({}, {}) //false
Object.is(3, '3') //false
Object.is(3, 3) //true
Object.is(true, true) //false
Object.is(false, 0) //false4、零值相等
与同值相等类似,零值相等认为 +0 和 -0 是相等的。
Object.is()实现方案
// 实现方案:
Object.defineProperty(Object, "is", {
value: function (x, y) {
if (x === y) {
// 需要区分一下+0和-0
return x !== 0 || 1 / x === 1 / y
} else {
// 需要区分一下NaN
return x !== x && y !== y
}
}
})总结
到此这篇关于 JavaScript 相等判断避坑的文章就介绍到这了,更多相关 JavaScript 相等判断避坑内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!