「JavaScript的不少奇技淫巧,都來自於對運算符的靈活使用。」框架
1.1 優先級: 優先級高的運算符最早被執行學習
問題: 1 || 1 ? 2 : 3 ; 答案:2 解析:||的優先級高 至關於: (1 || 1 )? 2 : 3 而不是: 1 || (1 ? 2 : 3 )
1.2 關聯性: 運算符執行時的方向。是從左向右,仍是從右向左spa
問題:+function (){var a = b = 1;}(); console.log(b); console.log(a); 答案:1 error 解析:賦值從右到左,var a = b = 1因此至關於 b = 1; var a = b; 那有同窗可能會問,爲何不是? var b = 1; var a = b; 還記得變量提高嗎?var a = b = 1;在變量提高的時候,只會把a去聲明,並不會執行賦值中的b。 因此要想把b也聲明瞭就須要按照語法 var a=1 , b ;
如今咱們仔細把優先級的題改一下code
1 || fn() && fn()
MDN上寫的是優先級高的運算符最早被執行,咱們都知道 ||是短路的,後邊不會執行。那麼這個最早被執行的含義是什麼呢?ip
1.3 短路:rem
問題:1 || fn() && fn() 答案:1 fn不會執行 解析:就是利用&&運算符的短路原理啊。
講到這有些同窗會以爲很簡單啊,就是這樣啊,看到短路後邊就不用算了啊。也有的同窗可能會有點懵,不是說好了, 優先級高的先被執行嗎?明明&&的優先級高啊。哈哈,別吵吵,咱們一塊兒看下一題。it
問題:var a = 42; var b = "foo"; var c = 0; c || b ? a : b ; // 42
剛纔說短路的同窗可能會說仍是要參考優先級。剛纔說優先級的同窗可能一臉懵逼,靜靜地不想說話。那麼咱們開始今天的學習吧。io
定義:運算符的優先級高先執行,並非真正的執行,而是更強的綁定。console
咱們用上面來兩個問題function
1 || fn() && fn() // &&的優先級高,因此將後邊的綁定 1 ||(fn() && fn()) // 因此至關於1 和(fn() && fn())的值去邏輯或 1 ||(fn() && fn()) // 咱們查表,邏輯或從左到右執行。 1 ||(fn() && fn()) // 左執行,1是真值,因此短路,後邊不執行 問題: var a = 42; var b = "foo"; var c = 0; c || b ? a : b ; 答案:42 解析:c || b ? a : b ; //查表 條件運算符權重是4,邏輯與符權重是6,因此邏輯與有更強的綁定 (c || b )? a : b ; //(c || b )至關於條件運算符裏的條件 (c || b )? a : b ; //(c || b )值是0 ,因此值是 a
好,咱們在作兩題鞏固一下
問題: var a = 5; var b = 5; var c = 5+a+++b; [ a , c ] 答案: [6, 15] 解析: b = 5+a+++b; //查表 後置遞增權重17 前置遞增權重16 b = 5 +(a++)+ b; //++優先級更高,因此和綁定a綁定在一塊兒 b = 5 +(a++)+ b; //根據語法後置遞增先執行語句,後遞增 b = 5 +(a++)+ b; //執行語句時a是5,因此b是15 b = 5 +(a++)+ b; //a在進行自增,獲得6 問題: var a = 5; var b = 5; var c = ++a-b; [ a , c ] 答案: [6, 1] 解析: var c = ++a-b; //查表 前置遞增權重和一元減權重都是16,從左往右執行 var c = ++a-b; //根據語法前置遞增先遞增,後執行語句 a = 6 var c = ++a-b; //執行語句時a是6,因此b是1
看到這,同窗們可能恍然大悟,就這麼回事啊。別急,咱們來看下一題。 要解決這個問題,須要咱們理解下一節的概念。
問題: var a = 42; var b = "foo"; var c = 0; a && b || c ? c || b ? a : c && b : a
定義:運算符的關聯性去定義表達式的處理方向
來,用題說話
問題:a && b && c 的執行順序 解析:(1)兩個運算符都是&&,權重同樣。因此這個時候就要看關聯性。 (2)查表 &&的關聯性是從左到右 (3)因此表達式應該是 ( a && b ) && c 問題:a ? b :c ? d : e 的執行順序 解析:(1)兩個運算符都是條件運算符,權重同樣。因此這個時候就要看關聯性。 (2)查表條件運算符的關聯性是從右到左 (3)因此表達式應該是 a ? b :(c ? d : e )
好了,如今咱們就能夠輕鬆解決上面那個問題啦。
問題: var a = 42; var b = "foo"; var c = 0; a && b || c ? c || b ? a : c && b : a 答案: 42 解析:(a && b) || c ? c || b ? a :(c && b) : a //首先查表邏輯與權重是6最高 ((a && b) || c) ? c || b ? a :(c && b) : a //而後是邏輯或 ((a && b) || c) ? (c || b ? a :(c && b)) : a //兩個條件運算符,權重同樣。關聯性從右到左
啊、、有沒有很開心 最後的最後,咱們來說一個釋疑
釋疑顧名思義就是解釋調疑惑的地方,那最好的辦法就是加()。
若是你可以熟練運用優先級/關聯的規則,你的代碼能更簡潔,許多框架都是這樣寫的,很是漂亮。
可是你要叫不許,那就加()吧,千萬別逞能,美其名曰有助於代碼的可閱讀性。