JS 数据类型转换规则(三)- loose equals vs strict equals
引言
- 没错,这一篇要讲的是 宽松相等(loose equals) 和 严格相等(strict equals)
- 我们平时记得是
==检查值是否相等 ;===检查值和类型是否相等,其实不然。正确的解释是:”==“容许在相等比较中进行强制类型转换(比较的是转换后的值) ,而===不容许类型转换。如果类型不一样,则直接返回false - == 会进行类型转换,这也是今天要把它写入类型转换的原因
字符串和数字之间的比较
- 类型不一致时,字符串与数字做宽松比较,字符串会做 Number()的隐式转换
let a = '11';
let b = 11
console.log(a == b) // true
+++
Number('11') // 11
11 == 11
其他类型和布尔值的比较
- 类型不一致时,布尔值,则会进行Number()的隐式转换
let a = '11';
let b = true;
let c = false
console.log(a == b) // false
console.log(a == c) // false
+++
Number(true) // 1
Number(false) // 0
null和undefined之间的比较
- null 只和 undefined 相等
null == undefined // true
对象和非对象之间的比较
- 类型不一致时,对象会经过 Symbol.toPrimitive -> valueOf()-> toString()。转换之后,和非对象进行比较
let a = 42;
let b = [42];
console.log(a == b)
+++
1. [42][Symbol.toPrimitive] // undefined
2. [42].valueOf() // [42]
3. [42].toString() // '42'
4. Number('42') // 42
所以 a == b
对象 和对象比较
- 比较的是堆内存地址,地址相同则相等
比较少见的情况
- 通过
对象和非对象之间的任一比较环节,去改变返回值。会影响整个结果
Number.prototype.toString = () =>{
return 3
}
new Number(2) == 3 // true
所以下面这道题就会变得很简单
```js
if (a == 2 && a == 3 && a == 4) {
// ...
}
只需要在对象和非对象之间比较的任一环节,改变返回值即可。
let arr = [2,3,4]
arr.toString = arr.shift
if (arr == 2 && arr == 3 && arr == 4) {
console.log('both ok')
}
如果类型一致,则不会继续做类型转换
[] == true // flase
![] == true // false
+++
true=> Number(true) // 1
[] => Number([]) // 0
所以 [] == true 是false
+++
![] => Boolean(![]) // false
fase == true // 此时类型一致,不再进行比较,结果 是flase
练习
- 0 == {} // false
2. 0 == null // false
这是一个特殊的,因为 null 只和undefined 相等,不做类型转换
- '' == [] // true
转换为
''之后,因为类型已经相等,所以不再进行类型转换
- false == [] // true
总结
==和===选择哪一个取决于是否容许在相等比较中发生强制类型转换。比如无法判断后端返回的是数字还是字符串,判断 null 和undefined时,建议使用==。除此之外,还是使用全等吧,毕竟安全- 个人建议,无论在什么情况下,都不要使用 == true 和 == false。 因为如果类型不同,会转Number。
最后
- 看过很多库的实现,对类型的把控是很严格的,都会显示的进行强制类型转换,防止隐式带来不必要的麻烦
- 到这里,数据类型转换就要告一段落了,如有疑问可以看往期文章。