值的比较

值的比较
古月值的比较
在Javascript
中,比较大小使用大于(>
)、小于(<
)、大于等于(>=
)、小于等于(<=
) 4个比较运算符,比较相等使用普通相等(==
)和严格相等(===
)
这里分成比较大小和比较相等,这两者是独立的,是两套独立的比较机制
先看一个例子,是不是很奇怪?看到后面就知道咋回事了
1 | null > 0 // false |
比较的结果都返回布尔值,要么true
,要么false
1 | 2 > 1 // true |
比较大小
比较大小有以下几种情况
如果比较双方都是字符串,则根据它们所包含的
Unicode
码位的值,将它们作为字符串进行比较。
会按照下面的方式进行比较
1.比较两个字符串的首位字符大小
2.如果这两个字符大小不相等,比较结束
3.否则继续比较下一位
4.重复上述比较,直到有一个字符串到达最后一个字符
5.如果到达最后一个字符两者还相等,则判定两个字符串相等,否则还有剩余字符的字符串更大
看几个例子1
2'aa' < 'ab' // true 第一个字符a相等,比较第二个字符,a的Unicode码的值比b小
'abcd' > 'abc' // true 在比较完abc之后,前面的字符还有剩余字符d比较双方不都是字符串时,会将两边的操作数转化为数值类型(可以当做
Number
类型)对象会依次调用其
[Symbol.toPrimitive]()
、valueOf()
和toString()
方法先将对象转换为基本类型,然后如果转换后的基本类型不是数值类型,再进一步转换为数值类型[Symbol.toPrimitive]()
可以自定义对象在强制转换为基本类型时如何返回基本类型值,可在MDN上查看这里需要注意的是,依次调用
[Symbol.toPrimitive]()
、valueOf()
和toString()
时,如果前一个返回的结果不是基本类型,会继续调用下一个,如果调用toString()
之后返回的还不是基本类型,进行判断时会报错1
2
3
4
5
6var arr = [];
// arr.valueOf()返回的是[],会继续走到toString(),手动改一下toString()就行
arr.toString = function() {
return []
}
console.log(arr > 1) // 报错 Uncaught TypeError: Cannot convert object to primitive value布尔值
true
和false
分别转化为 1 和 0。null
转化为 0。**
undefined
转化为NaN
**。字符串根据其包含的值进行转换,如果不包含数字值,则转换为
NaN
。
注意:字符串在转换为数字时,会忽略两端的空白字符(空格、换行符
\n
、制表符\t
等),然后尝试把剩下的字符转换为数字,相当于使用Number()
函数去转换,转换失败返回NaN。最开始我以为只要剩下的字符包含了非数字字符就会返回NaN,实际上并不是,因为16进制也是可以转换的,下面的例子能够正常转换。1
Number(' \n 0xa1 \n\t') // 161 0xa1表示16进制,会转换为10进制
如果任意一个值为
NaN
,则运算符返回false
。(NaN
和任何值进行大小比较都会返回false,进行相等比较也会返回false,包括比较它自己)否则,这些值将作为数值进行比较。BigInt 和数值可以一起比较。
1 | const obj = { |
比较相等
- 普通相等(
==
)
- 如果比较双方类型相同,这样比较
- 对象(Object):仅当两个操作数引用同一个对象时返回
true
。 - 字符串(String):仅当两个操作数具有相同的字符且顺序相同时返回
true
。 - 数字(Number):如果两个操作数的值相同,则返回
true
。+0
和-0
被视为相同的值。如果任何一个操作数是NaN
,返回false
;NaN
永远不等于NaN
。 - 布尔值(Boolean):仅当操作数都为
true
或都为false
时返回true
。 - 大整型(BigInt):仅当两个操作数的值相同时返回
true
。 - 符号(Symbol):仅当两个操作数引用相同的符号时返回
true
。
如果其中一个操作数为
null
或undefined
,另一个操作数也必须为null
或undefined
以返回true
。否则返回false
。如果其中一个操作数是对象,另一个是原始值,则将对象转换为原始值。
在这一步,两个操作数都被转换为原始值(字符串、数字、布尔值、符号和大整型中的一个)。剩余的转换将分情况完成。
如果是相同的类型,使用步骤 1 进行比较。
如果其中一个操作数是符号而另一个不是,返回
false
。如果其中一个操作数是布尔值而另一个不是,则将布尔值转换为数字:true 转换为 1,false 转换为 0。然后再次对两个操作数进行普通相等比较。
数字与字符串:将字符串转换为数字。转换失败将导致 NaN。
数字与大整型:按数值进行比较。如果数字的值为 ±∞ 或 NaN,返回 false。
字符串与大整型:使用与 BigInt() 构造函数相同的算法将字符串转换为大整型数。如果转换失败,返回 false。
严格相等(
===
)
相较于普通相等,严格相等不会做任何的类型转换,如果两者类型不同,直接返回false
还有一个Object.js()方法也可以判断两个值是否相等,它和严格相等唯一的区别有两点:1.带符号的0和NaN
1 | +0 === -0 // true |
好了,看一下最开始的问题,现在应该知道答案了
1 | null > 0 // false |
- null > 0 ;这里是进行大小比较,两边都会转换为数值,null转换为0,0 > 0为false
- null == 0;这里是进行普通相等比较,null和undefined在进行普通相等比较时,只有它们两者会相互相等,所以这里也是false
- null >= 0;这里进行大小比较,两边都会转换为数值,null转换为0,0 >= 0,返回true
来几道题练练手
题目1:判断以下比较的结果
- [] == ![]
- [] == []
- [1,2] == “1,2”
- [1,2] > [1,3]
- [1,2] > null
题目2:判断以下比较的结果
- 2 > true > false
- 2 > true > 1
- undefined > 0 > null
题目3:判断以下比较的结果
1 | const obj1 = { |
题目4:判断以下比较的结果
- Number.MIN_VALUE > 0
- Number.MIN_VALUE < 0
- -Number.MIN_VALUE > 0
- -Number.MIN_VALUE < 0
题目5:判断以下比较的结果
- ‘0xff’ > 255
- ‘0xff’ > ‘255’
- 255n > ‘254’
- ‘255’ > 254n
题解:
题目1和题目2:
1 | [] == ![] // true,这里有一个逻辑运算符!(非),它的优先级在逻辑运算符里面最高,优先处理![], |
题目3:
1 | const obj1 = { |
题目4:可以查看MDN上对于Number.MIN_VALUE的定义,它表示的是最小正数值。
1 | Number.MIN_VALUE > 0 // true |
题目5:
1 | '0xff' > 255 // false '0xff'转换成255 |