一、 引子
先上题,得出心中答案,打开浏览器点开F12,复制下面代码,看看结果。
console.log( [] == ![] )
console.log( {} == !{} )
剖析一下,主要分为:
!
逻辑运算符的优先级,{}
与[]
复杂数据类型如何转换;==
JS的数据类型的强制转换比较;
二、 逻辑运算符的优先级
运算符优先级本身是一种规则,该规则在计算表达式时控制运算符执行的顺序。具有较高优先级的运算符先于较低优先级的运算符执行。
先看MDN运算符优先级图表截取:
优先级 | 运算类型 | 关联性 | 运算符 |
---|---|---|---|
20 | 圆括号 |
n/a | ( … ) |
19 | new (带参数列表) |
从左到右 | new … ( … ) |
函数调用 | 从左到右 | … ( … ) | |
16 | 逻辑非 | 从右到左 | ! … |
一元加法 | 从右到左 | + … | |
一元减法 | 从右到左 | - … | |
10 | 等号 | 从左到右 | … == … |
6 | 逻辑与 | 从左到右 | … && … |
5 | 逻辑或 | 从左到右 | … || … |
在截取的表格中可以清晰的看到,逻辑非!
的优先级明显高于==
等号的有优先级,因此第一个问题,在[] == ![]
中最优先运算的是![]
,然后才是==
比较。
三、 复杂的数据类型如何转换
console.log(![]) // false
,这个结果相对好理解
注意: !
带有隐式转换
1、undefined(未定义,找不到值时出现)
2、null(代表空值)
3、false(布尔值的false,字符串"false"布尔值为true)
4、0(数字0,字符串"0"布尔值为true)
5、NaN(无法计算结果时出现,表示"非数值";但是typeof NaN==="number")
6、""(双引号)或''(单引号) (空字符串,中间有空格时也是true)
6种值转化为布尔值时为false
。
当前结论 ![] == false
当然,在使用==
时永远不要大意!参见 附1;
接下来,难题在于,[]
如何转化进行比较。
请先记住一个比较的基本规则:
数组与数值进行比较,会先转成数值,再进行比较;与字符串进行比较,会先转成字符串,再进行比较;与布尔值进行比较,两个运算子都会先转成数值,然后再进行比较。
遵循上边的规则(左侧x为数组时),需要将[]
与false
一并转化为数字类型后再进行比较。
OK,那么这个规则是谁说的算的呢?
截取一张知乎大佬贴的Es5 规范元知识图,上述比较参见 7 条。附2
参照第7条,ToNumber(false) // 0
为啥呢?上图
[]
依照图1,进入第9条,使用ToPrimitive([])
,上图
好吧,要根据类型默认使用DefaultValue
方法,上图
[]
属于字符串hint,那么执行toString()
console.log([].toString()) // "";
终于,表达式看起来不费劲了,"" == false
;
其实现在我们已经看到答案了,但是依据Es5==
的规范,我们还需要将字符串和布尔类型转化为数字类型最终比较;
false
参照图2,字符串参照图1第5条,ToNumber("") // 0
;
每次对比Es5规范真的好麻烦,所以
结尾总结了一下可以快速判断==
转化判断依据的原则,不必每次都参照图1啦 - 附3
完美
0 == 0 // true
附1 相等运算符(==)隐藏的类型转换,会带来一些违反直觉的结果,下面整理一些:
0 == '' // true
0 == '0' // true
2 == true // false
2 == false // false
"2" == true // flase
// 参见图1第7条
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
// \t \r \n都是转义字符,空格就是单纯的空格,输入时可以输入空格
// \t 的意思是 横向跳到下一制表符位置
// \r 的意思是 回车
// \n 的意思是回车换行
附2
附3
-
x == y
同类型原则总结:Number
比数值(+0,-0相等);String
比长短与字符序列(charCode)
;Boolean
中false == false; // true;
- 复杂数据类型比较引用地址;
-
x == y
不同基础数据类型比较原则总结:- x或y出现
NaN
一定返回false; - x或y出现
Boolean
一定全部转化数字后在比较; - x或y出现
Number
一定全部转化数字后比较;
- x或y出现
-
x == y
包含复杂数据类型原则:- x或y出现复杂数据类型通过
valueOf()
或toString()
转化为基本数据类型, 然后参照上述规则比较;
- x或y出现复杂数据类型通过
-
x == y
特殊总结:Null
与Undefined
除彼此或自身外,一律返回false
;NaN == NaN; // false
引用原地址:
- www.zhihu.com/question/29… // 知乎
- blog.csdn.net/qiqi_77_/ar… // CSDN
- lzw.me/pages/ecmas… // ES5规范中文站