今天逛微博的時候看到有個博主發的一個問題,代碼以下:函數
('b' + 'a' + + 'a' + 'a').toLowerCase()
// "banana"
複製代碼
當時第一反應是JavaScript會報錯,可是並無。而後就來了興趣ui
後來仔細一想,估計和JavaScript運算符優先級、隱式轉化有關係。spa
因而先去MDN查了一下JavaScript運算符優先級code
我先把上面代碼用到的運算符和優先級列舉出來:cdn
優先級 | 運算類型 | 關聯性 | 運算符 |
---|---|---|---|
20 | 圓括號 | n/a | (...) |
16 | 一元正號 | 從右至左 | + ... |
13 | 加法 | 從左至右 | ... + ... |
OK,瞭解了上面的運算符後,咱們如今來拆分下上面的代碼對象
首先把toLowerCase
去掉,這個函數沒啥用,只是起到一個迷惑的做用。blog
'b' + 'a' + + 'a' + 'a'
// to
'b' + 'a' + (+ 'a') + 'a'
複製代碼
這就是主要的,由於一元正號的優先級是比加法高的,因此這裏用括號標註一下。ip
如今咱們來看下一元正號
的說明:字符串
一元正號運算符位於其操做數前面,計算其操做數的數值,若是操做數不是一個數值,會嘗試將其轉換成一個數值。 儘管一元負號也能轉換非數值類型,可是一元正號是轉換其餘對象到數值的最快方法,也是最推薦的作法,由於它不會對數值執行任何多餘操做。它能夠將字符串轉換成整數和浮點數形式,也能夠轉換非字符串值 true,false 和 null。小數和十六進制格式字符串也能夠轉換成數值。負數形式字符串也能夠轉換成數值(對於十六進制不適用)。若是它不能解析一個值,則計算結果爲 NaN。get
注意看上面的這段話:若是操做數不是一個數值,會嘗試將其轉換成一個數值
和若是它不能解析一個值,則計算結果爲 NaN
那上面代碼的+ 'a'
就是會變成NaN
,過程以下:
'b' + 'a' + (+ 'a') + 'a'
// to
'b' + 'a' + Number('a') + 'a'
// to
'b' + 'a' + NaN + 'a'
複製代碼
是否是清晰不少了,而後又涉及到了隱式轉化,加號在JavaScript規則裏有一條是,當操做符有一個是字符串類型時,另外一個也要轉成字符串類型。也就是說NaN
要進行toString
。那NaN
在執行是什麼呢?在ECMA-262
中有說明,如圖:
也就是說NaN
會轉成"NaN"
。因此上面的代碼就變成了這樣:
'b' + 'a' + NaN + 'a'
// to
'b' + 'a' + "NaN" + 'a'
複製代碼
最終在調用toLowerCase
函數轉成小寫,就變成了banana
更正:
沒有必要爲了噴而噴,誠然文章的主體可能並非說有什麼實用價值。可是研究自己就是一件充滿樂趣的事情。開心就好。
不喜歡,關閉就好。於其浪費時間噴一下,不如去看一下其餘的文章。