js有关 == 容易出错点
前言
在js中有关 == 的用法,看起来不难;但是很多细节不注意将很容易出错,而且比其他语言都容易出错。这也是js弱类型语言的特性。
案例
先来一组简单的,看一下是否遇到过相应的问题
console.log("" == 0)//true
console.log([] == 0) //true
console.log({} == 0) //false
console.log(undefined == 0) //false
console.log(null == 0) //false
console.log(null == undefined) //true
再看一组有点难度的,看能否理解
console.log([] == [])//false
console.log([] == ![]) //true
console.log({} == {}) //false
console.log({} == !{}) //false
console.log(+'sss' == +'sss') //false
案例解决
要弄懂这些结果就必须了解一下js == 表达式的底层处理机制 如下图
如上图所示 先把上面11个案例一个一个对着跑一下
1. 空字符串和0 相等
console.log("" == 0)//true
带入上图公式第5行 x为字符串 y为数组 所以转化如下
console.log(Number('') == 0)//0==0 true
2. 空数组和0 相等
console.log([] == 0)//true
这里面就有一个ToPrimitive(抽象操作)知识点了
抽象操作 ToPrimitive
(参见 ES5 规范 9.1 节)会首先(通过内部操作 DefaultValue,参见 ES5 规范 8.12.8 节)检查该值是否有 valueOf() 方法。如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用 toString() 的返回值(如果存在)来进行强制类型转换。如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。
大致意思就是把先进行valueOf()操作 返回的值是不是基本类型,不是基本类型 就进行toString()操作看返回是不是基本类型
上面的 [] == 0;
就要进行流程图的第10行 x typeof x 为object 执行ToPrimitive() 操作
console.log([].valueOf())//[]
console.log([].toString())//""
可以得到结果时 [] 进行ToPrimitive() 得到的值为 “” 这样比较的 就是和案例1一样的返回为true
3.空对象和0 不相等
console.log({} == 0)//false
和上题一样当 对{}做ToPrimitive()操作
console.log([].valueOf())//{}
console.log([].toString())//"[object Object]"
再进行比较的话就是 “[object Object]” == 0 字符串和数字比较 字符产进行tonumber操作返回false
4.undefined和0不相等、null 和0 不相等、 .undefined和null相等
console.log(undefined == 0)//false
console.log(null == 0) //false
console.log(null == undefined) //true
根据上图undefined 只和本身 或者null相等,其他都不相等
5.[]和[]不相等,{}和{}不相等
console.log([] == [])//false
看起来一样却不相等,根据上图和所有的比较模块都不符合最后返回false;
关于引用类型的比较要比较其地址是否相等,地址相等两个才相等。如下:
var a = [];
var b = a;
var c = a;
console.log(b == c)//true
6.[]和![]相等
console.log([] == ![])//true
这个知识点就比较多了
- 运算符优先级
- !的用法
- ==的用法
运算符优先级如下图:
1.!的运算优先级比==高所以先执行![];
console.log(![])//false
![]为啥是false呢? 因为[] 是一个引用类型 他有一个引用地址。所以[] 为true;如下
if([]){
console.log('sss')
}
//sss
2.在执行 [] == false;
3.对[]进行ToPrimitive()操作 执行
console.log('' == false) // true
7.+'sss’和+‘sss’ 不相等
console.log(+'sss' == +'sss') //false
又是两个看起来一样的 这里其实用到了 下次我准备更新的js + 的用法
优先级+先执行 +"sss"执行结果为NaN
直接就是
返回false。
总结
有关js == 用法的总结如下:
- 都为引用类型比较时 比较其地址 地址一致则相等,否则不相等
- 引用类型和其他类型比较时 先对引用类型做ToPrimitive()操作 再进行比较
- 都为number类型时 有一个为NaN 返回false