JavaScript提供了两种相等的运算符:==
和 ===
。
一、相等(==)运算符
- 相等(==)运算符用来比较相同类型的数据时,与严格相等(===)运算符完全一样。
- 比较不同类型的数据时,相等(==)运算符会先将数据进行类型转换,然后再用严格相等(===)运算符比较。
比较时,会遵循以下的规则:
- 如果比较的两个操作数中,有一个操作数是
布尔值
或者字符串
,则尝试将布尔值和字符串转换为数值后,再比较两个操作数是否相等。
const result1 = (true == 1) // true
const result2 = (true == "1") // true
const result3 = (false == 0) // true
const result4 = (false == "0") // true
const result5 = (true == "") // false
const result6 = (false == "") // true
- 如果一个操作数是
字符串
,另一个操作数是数值
,则尝试将字符串转换为数值后,再比较两个操作数是否相等。
const result1 = ("1" == 1) // true
const result2 = ("0" == 0) // true
null
和undefined
比较时,结果为true
,null
和undefined
与其它类型的值比较时,结果为false
。
const result1 = (null == undefined) // true
const result2 = (0 == null) // false
const result3 = (0 == undefined) // false
const result4 = (true == null) // false
const result5 = (true == undefined) // false
const result6 = ("" == null) // false
const result7 = ("" == undefined) // false
- 如果有一个操作数是
NaN
,则两个操作数比较的结果返回false
。
const result1 = (true == "true") // false
// 等同于 Number(true) === Number("true")
// 等同于 1 === NaN
const result2 = (NaN == NaN) // false
- 如果两个操作数都是对象(这里的对象指广义的对象,包括数组和函数),则比较它们是不是同一个对象。如果两个对象都指向同一个内存地址,则相等操作符返回
true
const obj1 = { name: "Oct13_JJP" }
const obj2 = { name: "Oct13_JJP" }
const result1 = (obj1 == obj2) // false
const obj3 = { name: "Oct13_JJP" }
const obj4 = obj3
const result2 = (obj3 == obj4) // true
二、严格相等(===)运算符
- 如果两个操作数的类型不同,直接返回
false
。
const result1 = (true === "true") // false
const result2 = (1 === "1") // false
- 如果两个操作数的类型相同,值也相同,则返回
true
。
const result1 = (1 === 1) // true
const result2 = (1 === 0x1) // true
// 上面代码中,0x1是十六进制的1,与十进制的1比较,因为数据类型相同,值也相同,所以返回 true
null
和undefined
与自身严格相等。
const result1 = (null === null) // true
const result2 = (undefined === undefined) // true
- 变量声明后默认值是
undefined
,因此两个只声明未赋值的变量是相等的。
let v1, v2;
let result1 = (v1 === v2) // true
- 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个地址。
const obj1 = {}
const obj2 = {}
const result1 = (obj1 === obj2) // false
const arr1 = []
const arr2 = []
const result2 = (arr1 === arr2) // false
const fun1 = () => {}
const fun2 = () => {}
const result3 = (fun1 === fun2) // false
上面的代码分别比较两个空对象obj1和obj2、两个空数组arr1和arr2、两个空函数fun1和fun2,结果都是false。原因是:对于复合类型的值,严格相等运算比较的是,它们是否引用同一个内存地址,而运算符两边的空对象、空数组、空函数的值,都存放在不同的内存地址,所以结果是 false
。
- 如果两个变量引用同一个对象,则用严格相等运算比较时,结果是
true
。
const obj1 = {}
const obj2 = obj1
const result1 = (obj1 === obj2) // true
const arr1 = []
const arr2 = arr1
const result2 = (arr1 === arr2) // true
const fun1 = () => {}
const fun2 = fun1
const result3 = (fun1 === fun2) // true
- 注意:
NaN
与任何值都不相等(包括自身)。
const result1 = (NaN === NaN) // false
正 0
等于负 0
。
const result1 = (+0 === -0) // true
对于两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值。
new Date() > new Date() // false
new Date() < new Date() // false
new Date() === new Date() // false
三、总结
-
相等(==)运算符
- 如果两个操作数都为简单类型,字符串和布尔值会先转换成对应的数值,再进行比较
- 如果简单类型与引用类型比较,对象转化成其原始类型的值,再比较
- 如果两个操作数都为引用类型,则比较它们是否指向的是同一个内存地址
- null 和 undefined 相等
- 存在 NaN 则返回 false
-
严格相等(===)运算符
- 如果两个操作数的类型不同,比较的结果就是 false。
- 如果两个操作数都是 null 或都是 undefined,比较的结果是 true。
- 如果两个操作数是数字,并且值相同,除非其中一个或两个都是 NaN (这种情况下比较,结果是 false),否则它们是等同的。值 NaN 不会与其他任何值等同,包括它自身。
- 如果两个操作数都是字符串,而且在字符串中同一位置上的字符完全相同,那么它们就完全等同。如果字符串的长度或内容不同,它们就不是等同的。
- 如果两个操作数都是布尔型 true,或者两个操作数都是布尔型 false,那么它们等同。
- 如果两个操作数引用的是同一个对象、数组或函数,那么它们完全等同。如果它们引用的是不同的对象、数组或函数,它们就不完全等同,即使这两个对象具有完全相同的属性,或两个数组具有完全相同的元素。
- null 和 undefined 严格相等
四、什么情况下使用 == 和 === 运算符
- 相等运算符隐藏的类型转换,会带来一些违反直觉的结果。
0 == '' // true
0 == '0' // true
2 == true // false
2 == false // false
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
- 在比较值是否等于
null
的情况的时候,我们一般使用相等运算符(==
)。.
const obj = {};
if(obj.name == null){
console.log("该语句被执行"); // 该语句被执行
}
// 上面的代码等同于
const obj = {};
if(obj.name === null || obj.name === undefined) {
console.log("该语句被执行"); // 该语句被执行
}
- 因此,除了在比较对象属性为
null
或者undefined
的情况下,我们可以使用相等运算符(==
),其他情况建议使用严格相等运算符(===
)。