JavaScript 裏有三個邏輯運算符:||
(或),&&
(與),!
(非)。javascript
雖然他們被稱爲「邏輯」運算符,但這些運算符卻能夠被應用於任意類型的值,而不只僅是布爾值。他們的結果也一樣能夠是任意類型。html
讓咱們來詳細看一下。java
兩個豎線符號表示了「或」運算:react
result = a || b;
複製代碼
在傳統的編程中,邏輯或僅可以操做布爾值。若是參與運算的任意一個參數爲 true
,返回的結果就爲 true
,不然返回 false
。算法
在 JavaScript 中,邏輯運算符更加靈活強大。可是首先咱們看一下操做數是布爾值的時候發生了什麼。編程
下面是四種可能的邏輯組合:微信
alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false
複製代碼
正如咱們所見,除了兩個操做數都是 false
的狀況,結果都是 true
。ide
若是操做數不是布爾值,那麼它將會被轉化爲布爾值來參與運算。函數
例如,數字 1
將會被做爲 true
,數字 0
則做爲 false
:學習
if (1 || 0) { // 工做原理至關於 if( true || false )
alert( 'truthy!' );
}
複製代碼
大多數狀況,邏輯或 ||
會被用在 if
語句中,用來測試是否有 任何 給定的條件爲 true
。
例如:
let hour = 9;
if (hour < 10 || hour > 18) {
alert( 'The office is closed.' );
}
複製代碼
咱們能夠傳入更多的條件:
let hour = 12;
let isWeekend = true;
if (hour < 10 || hour > 18 || isWeekend) {
alert( 'The office is closed.' ); // 是週末
}
複製代碼
上文提到的邏輯處理多少有些傳統了。下面讓咱們看看 JavaScript 的「附加」特性。
拓展的算法以下所示。
給定多個參與或運算的值:
result = value1 || value2 || value3;
複製代碼
或運算符 ||
作了以下的事情:
true
,就中止計算,返回這個操做數的初始值。false
),則返回最後一個操做數。返回的值是操做數的初始形式,不會作布爾轉換。
也就是,一個或 "||"
運算的鏈,將返回第一個真值,若是不存在真值,就返回該鏈的最後一個值。
例如:
alert( 1 || 0 ); // 1(1 是真值)
alert( true || 'no matter what' ); //(true 是真值)
alert( null || 1 ); // 1(1 是第一個真值)
alert( null || 0 || 1 ); // 1(第一個真值)
alert( undefined || null || 0 ); // 0(全部的轉化結果都是 false,返回最後一個值)
複製代碼
與「純粹的、傳統的、僅僅處理布爾值的或運算」相比,這個規則就引發了一些頗有趣的用法。
獲取變量列表或者表達式的第一個真值。
假設咱們有幾個變量,它們可能包含某些數據或者是 null/undefined
。咱們須要選出第一個包含數據的變量。
咱們能夠這樣應用或運算 ||
:
let currentUser = null;
let defaultUser = "John";
let name = currentUser || defaultUser || "unnamed";
alert( name ); // 選出了 「John」 — 第一個真值
複製代碼
若是 currentUser
和 defaultUser
都是假值,那麼結果就是 "unnamed"
。
短路取值。
操做數不只僅能夠是值,還能夠是任意表達式。或運算會從左到右計算並測試每一個操做數。當找到第一個真值,計算就會中止,並返回這個值。這個過程就叫作「短路取值」,由於它儘量地減小從左到右計算的次數。
當表達式做爲第二個參數而且有必定的反作用(side effects),好比變量賦值的時候,短路取值的狀況就清楚可見。
若是咱們運行下面的例子,x
將不會被賦值:
let x;
true || (x = 1);
alert(x); // undefined,由於 (x = 1) 沒有被執行
複製代碼
若是第一個參數是 false
,或運算將會繼續,並計算第二個參數,也就會運行賦值操做。
let x;
false || (x = 1);
alert(x); // 1
複製代碼
賦值操做只是一個很簡單的狀況。可能有反作用,若是計算沒有到達,反作用就不會發生。
正如咱們所見,這種用法是「if
語句的簡短方式」。第一個操做數被轉化爲布爾值,若是是假,那麼第二個參數就會被執行。
大多數狀況下,最好使用常規的 if
語句,這樣代碼可讀性更高,可是有時候這種方式會很簡潔。
兩個 & 符號表示 &&
與操做:
result = a && b;
複製代碼
傳統的編程中,當兩個操做數都是真值,與操做返回 true
,不然返回 false
:
alert( true && true ); // true
alert( false && true ); // false
alert( true && false ); // false
alert( false && false ); // false
複製代碼
使用 if
語句的例子:
let hour = 12;
let minute = 30;
if (hour == 12 && minute == 30) {
alert( 'Time is 12:30' );
}
複製代碼
就像或運算同樣,與運算的操做數能夠是任意類型的值:
if (1 && 0) { // 做爲 true && false 來執行
alert( "won't work, because the result is falsy" );
}
複製代碼
給出多個參加與運算的值:
result = value1 && value2 && value3;
複製代碼
與運算 &&
作了以下的事:
false
,就中止計算,並返回這個操做數的初始值。true
),則返回最後一個操做數。換句話說,與操做符返回第一個假值,若是沒有假值就返回最後一個值。
上面的規則和或運算很像。區別就是與運算返回第一個假值而或操做返回第一個真值。
例如:
// 若是第一個操做符是真值,
// 與操做返回第二個操做數:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5
// 若是第一個操做符是假值,
// 與操做直接返回它。第二個操做數被忽略
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
複製代碼
咱們也能夠在一行代碼上串聯多個值。查看第一個假值是否被返回:
alert( 1 && 2 && null && 3 ); // null
複製代碼
若是全部的值都是真值,最後一個值將會被返回:
alert( 1 && 2 && 3 ); // 3,最後一個值
複製代碼
與運算
&&
在或操做符||
以前執行與運算
&&
的優先級比或運算||
要高。因此代碼
a && b || c && d
徹底跟&&
表達式加了括號同樣:(a && b) || (c && d)
。
就像或運算同樣,與運算 &&
有時候可以代替 if
。
例如:
let x = 1;
(x > 0) && alert( 'Greater than zero!' );
複製代碼
&&
右邊的代碼只有運算抵達到那裏才能被執行。也就是,當且僅當 (x > 0)
返回了真值。
因此咱們基本能夠相似地獲得:
let x = 1;
if (x > 0) {
alert( 'Greater than zero!' );
}
複製代碼
帶 &&
的代碼變體看上去更短。可是 if
的含義更明顯,可讀性也更高。
因此建議是根據目的選擇代碼的結構。須要條件判斷就用 if
,須要與運算就用 &&
。
感嘆符號 !
表示布爾非運算。
語法至關簡單:
result = !value;
複製代碼
操做符接受一個參數,並按以下運做:
true/false
。例如:
alert( !true ); // false
alert( !0 ); // true
複製代碼
兩個非運算 !!
有時候用來將某個值轉化爲布爾類型:
alert( !!"non-empty string" ); // true
alert( !!null ); // false
複製代碼
也就是,第一個非運算將該值轉化爲布爾類型並取反,第二個非運算再次取反。最後咱們就獲得了一個任意值到布爾值的轉化。
有更多詳細的方法能夠完成一樣的事 —— 一個內置的 Boolean
函數:
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
複製代碼
非運算符 !
的優先級在全部邏輯運算符裏面最高,因此它老是在 &&
和 ||
前執行。
先本身作題目再看答案。
重要程度:⭐️⭐️⭐️⭐️⭐️
以下代碼將會輸出什麼?
alert( null || 2 || undefined );
複製代碼
重要程度:⭐️⭐️⭐
下面的代碼將會輸出什麼?
alert( alert(1) || 2 || alert(3) );
複製代碼
重要程度:⭐️⭐️⭐️⭐️⭐️
下面這段代碼將會顯示什麼?
alert( 1 && null && 2 );
複製代碼
重要程度:⭐️⭐️⭐
這段代碼將會顯示什麼?
alert( alert(1) && alert(2) );
複製代碼
重要程度:⭐️⭐️⭐️⭐️⭐️
結果將會是什麼?
alert( null || 2 && 3 || 4 );
複製代碼
重要程度:⭐️⭐️⭐
寫一個「if」條件句來檢查 age
是否位於 14
到 90
的閉區間。
「閉區間」意味着,age
的值能夠取 14
或 90
。
重要程度:⭐️⭐️⭐
寫一個 if
條件句,檢查 age
是否不位於 14 到 90 的閉區間。
建立兩個表達式:第一個用非運算 !
,第二個不用。
重要程度:⭐️⭐️⭐️⭐️⭐️
下面哪個 alert
將會被執行?
if(...)
語句內表達式的結果是什麼?
if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );
複製代碼
重要程度:⭐️⭐️⭐
實現使用 prompt
進行登錄校驗的代碼。
若是訪問者輸入 "Admin"
,那麼使用 prompt
引導獲取密碼,若是輸入的用戶名爲空或者按下了 key:Esc
鍵 —— 顯示 "Canceled",若是是其餘字符串 —— 顯示 "I don't know you"。
密碼的校驗規則以下:
流程圖:
請使用嵌套的 if
塊。注意代碼總體的可讀性。
提示:將空字符串輸入,prompt 會獲取到一個空字符串 ''
。Prompt 運行過程當中,按下 key:ESC
鍵會獲得 null
。
在微信公衆號「技術漫談」後臺回覆 1-2-11
獲取本題答案。
現代 JavaScript 教程:開源的現代 JavaScript 從入門到進階的優質教程。React 官方文檔推薦,與 MDN 並列的 JavaScript 學習教程。
在線免費閱讀:zh.javascript.info
掃描下方二維碼,關注微信公衆號「技術漫談」,訂閱更多精彩內容。