浅谈数据比较的细节

基本类型的比较

布尔类型和数字类型

例:console.log(true == 1) // true

解析:这是由于比较的隐式转换原因,基本数据类型和数字类型比较,都会把该类型转成数字类型后,再和数字进行比较,因为true 转成数字后为1 ,所以相当于 1 = = 1 ,结果肯定为true。

字符类型和数字类型

例:console.log('10' == 1)  

解析:一样的,这里也是由于隐式转换原因,编译器把 ‘10’ 转换成了数字类型,字符转数字,结果肯定是NaN,所以就相当于 NaN = = 1,结果就为false。其他也类似,都是把字符转成数字后再比较。

布尔类型和字符类型

例:
	console.log(Boolean('x'));  // true
    console.log(true == 'x');   // false

解析:这是个很多人会判断错误的,以为布尔值和字符串的比较,是把另一个字符转换成布尔类型再比较,实则不是,实际上是将两边都转换成数字类型,再进行比较,比如以上例子,首先将true转成数字类型,得到1, 字符‘x’ 转成数字类型得到的是NaN,所以结果得到false。比较特殊的例子: true == ‘1‘, false == ‘0’ ,false == ’ ’ . 这几个就是相等的。

基本类型和复杂类型的比较

console.log( { name: 'jack' } == 10 )

解析:复杂类型和基本类型之间的比较,会先调用对象的valueOf方法,或者调用toString,具体看跟数字还是字符比较。然后再两边都转换成数字类型进行比较。在这题里,就相当于 Number({ name: ‘jack’ }.valueOf()) == 10,结果为NaN == 10,肯定为false。

复杂类型的比较

对象之间的比较

console.log( [] == [] ) // false
console.log( {} == {} ) // false

解析:两个对象比较,则比较的就为是不是同一个对象,相当于比较地址值是否一样。上面的例子很明显就为false,在未定义的情况下,使用[] 或者 {}都相当于进行了new的操作,所以两者为不同的对象。

下面来问一个问题:

let obj1 = {}
let obj2 = obj1 
console.log( obj1 == obj2 ) 

解析:很简单,答案是为true。原理就是,复杂类型之间的赋值,是地址值的赋值,obj1 把它的地址值赋值为 obj2 。所以他们的地址一样,比较结果为true。

重头戏:

第一题:

console.log( ![] == [] ) // true

解析:我想这个是很多很多小白(我也是)会被坑到的题目。下面慢慢讲解。
1.首先,这里有!,所以根据优先级,先算!. !会触发隐式转换,转换成boolean再进行取反。(null 、undefined、’ ’ 、0 、NaN为false,其他都为true)。所以第一步 ![] 即判断 !true 得到的结果则为 false .
2.所以现在的进行到了 false == [] ,这时候,就变成了一边是基本类型,一边是对象,编译器则会调用对象的valueOf(包装类型),没有则调用toString方法。

console.log([].toString()  === '')   // true

3.这说明,[]调用了toString方法后得到’ ’ 。所以,现在的判断来到了 false == ’ ’ , 就是布尔类型和字符类型的比较。所以两边都会转成数字 ,即 0 == 0,结果就为true。

根据这个原理判断一下这题:

console.log( ![10] == [10] ) 

解析:先算取反,就把[10]转成boolean,就是 true 再取反 false
即变成了 false == [10] ,一边有对象,会调用对象的valueOf或者toString,它调用toString,得到’10’ 。所以相当于判断false == ‘10’ 也就是判断 0 == 10 那么得到 false。

第二题:

console.log(!{} == {}) // false

解析:首先取反,得到false 相当于判断 false == {},再调用对象的toString 得到 [object Object],则变成了false == ‘[object Object]’ 再转成数字 得到 0 == NaN 就是 false。

基本包装类型的比较

基本包装类型则为String,Number,Boolean这个三个类型,他们可以使用new关键字以及点语法。所以称为基本包装类型。

let str2 = new String('10') 
console.log(str2 == 10) // true

解析:基本包装类型比较的时候主要是会用到valueOf这个方法,在这题,即 str2.valueOf() == 10 , 就得到 10 == 10,答案为true。

总结:

如果都是基本数据类型比较,最终会把他们都转成数字进行比较,同类型就是自己的值比较。
如果都是复杂类型,就比较地址(也就是比较是不是同一个对象)
如果一个基本类型一个复杂类型 ,就先把复杂类型调用valueOf或者toString转成基本类型,再按基本类型的规则来比较

注意:只要是{}和new Object这种对象,调用的toString都会变成 [object Object]

好了,本小白知识储备有限,能理解的就这么多了,希望能给广大前端学友起到帮助,如说的有误的,希望大佬在评论多多帮忙指正一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值