1、概念html
與其餘語言不一樣,在js中,邏輯運算符能夠返回任何類型的數據,不只僅是true和false。函數
&&和||的返回值是兩個操做數的其中一個。即a&&b或者a||b返回的是要麼是a,要麼是b,而其餘語言中返回的是true or false。優化
在js邏輯運算中,須要隱式的轉換爲boolean類型再來運算,轉換規則爲:spa
1. 對象、非零number、非空string——>true.net
2. 0、""、null、false、undefined、NaN——>falsecode
具體見下表:htm
數據類型 |
轉換爲boolean後的值 |
NAN | FALSE |
null | FALSE |
undefined | FALSE |
Object | TRUE |
Function | TRUE |
0 | FALSE |
非零的數字 | TRUE |
""(空字符串) | FALSE |
非空字符串 | TRUE |
所以:blog
a && b : 將a, b轉換爲Boolean類型, 再執行邏輯與, 若是結果是true返回b, false返回a
a || b : 將a, b轉換爲Boolean類型, 再執行邏輯或, 若是結果是false返回b, true返回第一個爲true的值。ip
邏輯&&和邏輯||還有一個短路原則:知道了前面第一個的結果就知道最後的輸出
a&&b:左操做數爲假值時,返回左操做數,不然返回右操做數。
a||b:左操做數爲假值時,返回右操做數,不然返回左操做數。
只要「||」前面爲false,無論「||」後面是true仍是false,都返回「||」後面的值。
只要「||」前面爲true,無論「||」後面是true仍是false,都返回「||」前面的值。
只要「&&」前面是false,不管「&&」後面是true仍是false,結果都將返「&&」前面的值;
只要「&&」前面是true,不管「&&」後面是true仍是false,結果都將返「&&」後面的值;
一樣對於多個操做數的狀況:
a||b||c||d:若結果爲true則返回第一個true值,若結果爲false則返回最後一個操做數。eg:var a = 「」 || null || 3 || 2 -> var a = fasel || false || true || true 結果爲true 則返回第一個true,便是3
a&&b&&c&&d:若結果爲false則返回第一個false,若結果爲true則返回最後一個操做數。eg:var b = 2&&null&&1&&0 -> var b = true&&false&&true&&false結果是false 則返回第一個false 便是null
2、理解
「&&」和「||」運算符都可以從三個不一樣的層次來逐步理解:
以「&&」爲例解釋以下:
(1)最簡單的第一層理解是,當操做數都是布爾值的時候,「&&」對兩個值執行布爾與(AND)操做,只有在第一個操做數和第二個操做數都是true的時候,它才返回true。若是其中一個操做數是false,它返回false。
(2)「&&」的操做數並不必定是布爾值。因而對「&&」的第二層理解是,「&&」能夠對真值和假值進行布爾與(AND)操做。若是兩個操做數都是真值,那麼返回一個真值;不然,至少一個操做數是假值的話,則返回一個假值。在JavaScript中任何但願使用布爾值的地方,表達式和語句都會將其當作真值或假值來對待,所以實際上「&&」並不老是返回true和false。
(3)第三層理解,運算符首先計算左操做數的值,即首先計算「&&」左側的表達式。若是計算結果是假值,那麼整個表達式的結果必定也是假值,所以「&&」這時簡單地返回左操做數的值,而並不會對右操做數進行計算。反過來說,若是左操做數是真值,那麼整個表達式的結果則依賴於右操做數的值。若是右操做數是真值,那麼整個表達式的值必定是真值;若是右操做數是假值,那麼整個表達式的值必定是假值。
理解以下例子對於理解「&&」可能不會去計算右操做數的狀況相當重要,在如下示例代碼中,變量p的值是null,而若是計算表達式p.x的話則會拋出一個類型錯誤異常。可是示例代碼使用了「&&」的一種符合語言習慣的用法,所以只有在p爲真值(不能是null或者undefined)的狀況下才會計算p.x。反過來,咱們通常須要用某個對象p中的某個元素時,爲了嚴謹也應該先對其是否存在進行判斷。
var o = { x : 1 }; var p = null; o && o.x // =>1:o 是真值,所以返回值爲o.x p && p.x //=>null: p是假值,所以將其返回,而並不去計算p.x
3、使用場景
1.||運算符最經常使用的方式是用來從一組備選表達式中選出第一個真值表達式,即從一系列值中獲取第一個true值。
// 若是max_width已經定義了,直接使用它;不然在preferences對象中查找max_width;若是沒有定義它,則使用一個寫死的常量 var max = max_width || preferences.max_width || 500;
2.判斷某個元素是否存在時:if(attr)寫成if(!!attr)更加嚴謹。
!!的做用是把一個其餘類型的變量轉成的bool類型。eg:
typeof 5//"number" typeof !!5//"boolean"
3.對函數中的參數賦以默認值:a=a||
"defaultValue"
;
例如當a不存在或不合法時爲其賦默認值,比起以下兩種寫法:
if(!a){ a="defaultValue"; }
if(a==null||a==""||a==undefined){ a="defaultValue"; }
用||一句話就能夠實現,簡單又優雅:
a=a||"defaultValue";
4.利用&&的短路特性有條件的執行代碼
(1)在回調中,常常這樣寫:callback&&callback(),先判斷 callback 是否是存在,存在才執行,這樣寫更加嚴謹,若是直接寫 callback(); 當callback不存在時代碼就會報錯。
(2)又或者常見的條件語句:if
(a==b) stop();若是用&&來實現即爲:
(a==b)&&stop();
(3)判斷某個對象存在再取值:p && p.x
應用舉例:
如圖:
假設對成長速度顯示規定以下:
成長速度爲5顯示1個箭頭;
成長速度爲10顯示2個箭頭;
成長速度爲12顯示3個箭頭;
成長速度爲15顯示4個箭頭;
其餘都顯示都顯示0個箭頭。
(1)最容易想到也最常規的方法:if-else
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 if(add_step == 15){ add_level = 4; } else { add_level = 0; }
(2)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; case 15 : add_level = 4; break; default : add_level = 0; break; }
(3)而若是用&&和||就會超級簡單:
var add_level = (add_step==5 && 1) || (add_step==10 && 2) || (add_step==12 && 3) || (add_step==15 && 4) || 0;
優化爲:
var add_level={'5':1,'10':2,'12':3,'15':4}[add_step] || 0; //對象取值有兩種方式,一種object.key,一種是object[key],此處爲法二
特別是若是需求改爲:
成長速度爲>12顯示4個箭頭;
成長速度爲>10顯示3個箭頭;
成長速度爲>5顯示2個箭頭;
成長速度爲>0顯示1個箭頭;
成長速度爲<=0顯示0個箭頭。
那麼用switch實現起來也很麻煩了,而一樣用&&和||只要以下便可。
var add_level = (add_step>12 && 4) || (add_step>10 && 3) || (add_step>5 && 2) || (add_step>0 && 1) || 0;
注:與&&和||不一樣,!操做符的行爲與C、Java等語言是一致的,只返回boolean值(true或false)。
參考:
http://www.cnblogs.com/yanayana/p/7079345.html