写作背景
因为不理解为什么null==false返回false
,而null>=false返回true
,所以对 JavaScript的比较运算符==、===、>=、!=的比较规则
部分的知识进行了查漏补缺。
1. == & ===
==是宽松相等,===是严格相等。两者的区别在于:当两边变量类型不相等时,== 会进行隐式转换。(null、undefined除外)
== 的比较规则
- 当两边类型相同时,若是原始类型则比较值,若是对象类型,则比较引用是否一致。
- 当两边类型不同时,触发隐式转换。
隐式转换规则
什么时候会触发隐式规则?当比较运算符两边的类型不相等时。(null、undefined除外)
- boolean vs any,布尔类型-> number
- Number vs String,String -> number
- 对象类型 vs 原始类型,对象类型 toPrimitive
- (null、undefined) vs any,null与非(null、undefined)的值比较总是返回false。
隐式转换的方法共有四种:toString、toNumber、toBoolean、toPrimitive
对于toString和toNumber:
toString | toNumber | |
---|---|---|
null | "null" | 0 (null可理解为no object) |
undefined | "undefined" | NaN |
true/false | "true"/""false | 1/0 |
10 | "10" | 10 |
"hello"/"123" | "hello"/"123" | NaN/123 |
[1,2,3,4]/[]/[1,null,2,undefined,3] | "1,2,3,4"/""/"1,,2,,3" | "1,2,3,4"/""/"1,,2,,3" |
{} | [objet Object] | [object Object] |
对于toBoolean: JS中假值只有6种:false、null、undefined、0、NaN、空字符,其他值转为布尔值全为true。
对于toPrimitive: 获取对象类型的valueOf方法的返回值。如果valueOf不存在/返回的不是原始类型的值,则获取对象的toString()方法的返回值,即遵循ToString规则。如果valueOf和toString都没返回值,则抛出异常。
注意:数组调用valueOf返回数组本身,所以数组一旦toPrimitive相当于调用toString。
2. >=
>= 的比较规则
- 如果两个变量都是String,则按照字典顺序和Unicode比较.如"cat">"Cat","cat1">"cat","2">"11"
- 如果两个变量都是原始类型,则转成数值比较。
- 如果变量是对象类型,则转成原始类型比较(toPrimitive)。
所以null==false返回false,但是null>=false,这是因为 == 比较依据是null与非(null、undefined)都不宽松相等,而 >= 将两边都转成number类型。
3. !=
其算法是先求宽松相等运算符的结果,然后返回相反值。
4. 验收学习成果
js
0 == '' // true
1 == '1' // true
1e21 == '1e21' // true
Infinity == 'Infinity' // true
true == '1' // true
false == '0' // true
false == '' // true
// NaN和任何人都不相等,包括它自己
null == false // false
undefined == false // false
[] == ![] // true
[] == 0 // true
[2] == 2 // true
['0'] == false // true
'0' == false // true
[] == false // true
[null] == 0 // true
null == 0 // false
[null] == false // true
null == false // false
[undefined] == false // true
// 首先变成 [undefined]==0
// 接着[undefined].valueOf()返回自身
// 接着调用toString返回""
// 所以""==0 返回true
undefined == false // false
// undefined 和 非(null、undefined)都返回false
[2,3,4]>=[2,3,4] // true
[2,3,4]==[2,3,4] // false
let a = [2,3,4]
a==a // true
a==[2,3,4]// false
[2,3,4]>=[1,2,3] // true
[2,3,4]>=[1,2,3,999] // true
JS
Number([]) // 0
Number(['10']) //10
const obj1 = {
valueOf () {
return 100
},
toString () {
return 101
}
}
Number(obj1) // 100
const obj2 = {
toString () {
return 102
}
}
Number(obj2) // 102
const obj3 = {
toString () {
return {}
}
}
Number(obj3) // TypeError
Reference
javascript学习之比较运算符_javascript 连续比较 <-CSDN博客 从一道面试题说起---js隐式转换踩坑合集 - 掘金 (juejin.cn)