Important

等值检测的目的是判断两个变量是否相等。这其中,运算符“==”和“!=”的运算效果称为“相等”和“不等”,而“===”和“!==”的运算效果称为“严格相等”和“严格不相等”。

运算符 名称 说明
== 相等 比较两个表达式,看是否相等
!= 不等 比较两个表达式,看是否不相等
=== 严格相等 是否相等并具有相同的数据类型
!== 不严格相等 是否具有不相等的值或不同的数据类型

等值检测中“相等“的运算规则

类型 运算规则
值类型与引用类型 将引用类型的数据转换为与值类型数据相同的数据,再进行”数据等值“比较
两个值类型 转换成相同数据类型的值进行”数据等值“比较
两个引用类型 比较引用地址

在三种值类型(数值、布尔值和字符串)中,如果两个被比较的值类型不同,那么:

表达式 结果
null == undefined true
"NaN" == NaN false
NaN == NaN false
false == 0 true
true == 1 true
true == 2 false
undefined == 0 false
null == 0 false
"5" == 5 true
{} == {} false

可见,JavaScript总是尽量用数字值比较来实现等值检测

等值检测中“严格相等“的运算规则

类型 运算规则
值类型与引用类型 必然不严格相等
两个值类型 如果数据类型不同,必然不严格相等;否则”数据等值“比较
两个引用类型 比较引用地址

虽然null == undefined 是 true,但 null === undefined 是false,因为它们不是相同的数据类型

Object.is()

在ECMAScript 6之前,有些特殊情况即使是===操作符也无能为力:
// 这些是===符合预期的情况
console.log(true === 1); // false
console.log({} === {}); // false
console.log("2" === 2); // false
// 这些情况在不同JavaScript引擎中表现不同,但仍被认为相等
console.log(+0 === -0); // true
console.log(+0 === 0); // true
console.log(-0 === 0); // true
// 要确定NaN的相等性,必须使用极为讨厌的isNaN()
console.log(NaN === NaN); // false
console.log(isNaN(NaN)); // true

为改善这类情况,ECMAScript 6规范新增了 Object.is(),这个方法与===很像,但同时也考虑到了上述边界情形。这个方法必须接收两个参数:
console.log(Object.is(true, 1)); // false
console.log(Object.is({}, {})); // false
console.log(Object.is("2", 2)); // false
// 正确的0、-0、+0相等/不等判定
console.log(Object.is(+0, -0)); // false
console.log(Object.is(+0, 0)); // true
console.log(Object.is(-0, 0)); // false
// 正确的NaN相等判定
console.log(Object.is(NaN, NaN)); // true