最近重新翻開原生JS,又得到很多不同的體會,雖然現在開發框架那么多,但很多思想都還是離不開原生的基礎。今天呢,我就根據自己的學習總結一下邏輯與(&&)和(邏輯或(||)和邏輯非(!)。
基本定義
||:邏輯或,只有表達式的值都為false,才返回false,其他情況返回true 比如:(8>5)&&(4<6),返回true;(8<5)&&(4<6),返回false
&&:邏輯與,若兩邊表達式的值都為true,才返回true;比如: (8>5)&&(4<6),返回true;(8<5)&&(4<6),返回false
!:邏輯非,若表達式的值為true,則返回false;若表達式的值為false,則返回true 比如:!(9>2),返回false;!(9<2),返回true,
這是他們的基本定義,我們都再熟悉不過了,看似好像沒有什么大用,其實這三個運算符在我們編寫代碼中所起到的重要作用。
首先看幾個例子
var a = 0 || 1 || 2;// a = 1
var b = 1 || 0 || 3;// b = 1
var c = 0 || 0 || 0;// c = 0
var a = 0 && 1 && 2;// a = 0
var b = 1 && 0 && 3;// b = 0
var c = 0 && 0 && 0;// c = 0
var d = 1 || 2 || 4;// d = 1
OK.看完上面的栗子,你會發現邏輯運算符不是簡單的返回true/false,而是返回了某一個內容,其實它的判斷過程是這樣的: 邏輯運算符是從前往后依次判斷,判斷到那個能得出最終結論的地方,就會停止往下判斷並返回最后判斷的那個內容,不管它是真是假。(記住這句話就行) 比如:||運算符,只要一個為真就為真,所以你可以認為它會從前往后一直按順序在找真,找到真就返回那個真。找不到也返回最后一個判斷的那個值。 0 || 1 || 2,判斷到1就知道結果肯定是真,不再繼續判斷,返回1。 1 || 0 || 3, 判斷到第一個就知道結果是真,不再繼續判斷,返回1。 0 || 0 || 0;一直判斷到了最后一個,才知道結果為假,返回最后一個判斷的0。 同理:&&運算符是只要一個為假就為假,所以它會從前往后一直找假的,返回最后一個判斷的值。
實際應用
1給函數參數定義默認值
var a = a||2; //判斷過程:如果變量a是真就停止判斷,返回a,如果a是假就繼續判斷,所以返回2. 實際上就是給a起了個默認值2。 也等同於: if(a){ a = a }else{ a =2 } //因為js不像php可以直接在型參數上定義func($attr=5)一個默認值,所以可以通過這種方法給參數定義默認值。(順便提醒一下,最新的es6標准已經可以定義函數參數默認值了。)
可以看出用邏輯運算符既節省代碼又實現功能
2 大大減少代碼量
首先出個題:假設:成長速度為5顯示1個箭頭;成長速度為10顯示2個箭頭;成長速度為12顯示3個箭頭;其他都顯示都顯示0各箭頭。
用代碼怎么實現?(例子來源於網上的一個貼吧里)
最簡單的
var add_level = 0; if(add_step == 5){ add_level = 1; }else if(add_step == 10){ add_level = 2; }else if(add_step == 12){ add_level = 3; }else { add_level = 0; }
稍好些的switch:
var add_level = 0; switch(add_step){ case 5 : add_level = 1; break; case 10 : add_level = 2; break; case 12 : add_level = 3; break; default : add_level = 0; break; }
更好的
var add_level = (add_step==5 && 1) || (add_step==10 && 2) || (add_step==12 && 3) || 0;
更更好的
var add_level={'5':1,'10':2,'12':3}[add_step] || 0;
等同於下面的代碼:
var obj = {'5':1,'10':2,'12':3};
var add_level=json[add_step] || 0;
如果需求改成:成長速度為>12顯示4個箭頭;成長速度為>10顯示3個箭頭;成長速度為>5顯示2個箭頭;成長速度為>0顯示1個箭頭;成長速度為<=0顯示0個箭頭。
var add_level = (add_step>12 && 4) || (add_step>10 && 3) || (add_step>5 && 2) || (add_step>0 && 1) || 0; console.log(add_level);
哇塞,是不是發現我們的代碼一下子就少了很多,但需要注意的一點就是:一方面精簡js代碼,能實質性的減少網絡流量,尤其是大量應用的js公用庫。同時,也帶來了代碼可讀性的降低,個人比較推薦的做法是:如果是相對復雜的應用,請適當地寫一些注釋。
我們可以不使用這些技巧,但是我們一定要能看懂,因為這些技巧已經廣泛應用,不理解這些你就很難看懂別人的代碼。
關於!運算符
很多代碼寫if(!!attr),為什么不直接寫if(attr);其實這是一種更嚴謹的寫法,如下:
console.log(typeof 5); //number console.log(typeof !!5); //boolean
可以看出:!的作用是把一個其他類型的變量轉成的bool類型。
不管!后面是什么類型,邏輯非都會將它轉成布爾類型
&& (邏輯與) 和||(邏輯或)的優先級:
混合使用的時候要注意他們的優先級:&& (邏輯與) 優先級高於||(邏輯或)
return a && b || c
先算a&&b,a 是 false ,a&&b就是返回a,再算a||c,則肯定返回 c;如果a是true ,則要看B,自己想想吧。。。
另附:JS運算符優先級(從高到低列出)
運算符 | 描述 |
. [] () | 字段訪問、數組下標、函數調用以及表達式分組 |
++ -- - ~ ! delete new typeof void | 一元運算符、返回數據類型、對象創建、未定義值 |
* / % | 乘法、除法、取模 |
+ - + | 加法、減法、字符串連接 |
<< >> >>> | 移位 |
< <= > >= instanceof | 小於、小於等於、大於、大於等於、instanceof |
== != === !== | 等於、不等於、嚴格相等、非嚴格相等 |
& | 按位與 |
^ | 按位異或 |
| | 按位或 |
&& | 邏輯與 |
|| | 邏輯或 |
?: | 條件 |
= oP= | 賦值、運算賦值 |
, | 多重求值 |
如有錯誤,歡迎指正。