W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
JavaScript 中有四個邏輯運算符:?||
?(或),?&&
?(與),?!
?(非),???
?(空值合并運算符)。本文我們先介紹前三個,在下一篇文章中再詳細介紹 ???
? 運算符。
雖然它們被稱為“邏輯”運算符,但這些運算符卻可以被應用于任意類型的值,而不僅僅是布爾值。它們的結果也同樣可以是任意類型。
讓我們來詳細看一下。
兩個豎線符號表示“或”運算符:
result = a || b;
在傳統(tǒng)的編程中,邏輯或僅能夠操作布爾值。如果參與運算的任意一個參數(shù)為 true
,返回的結果就為 true
,否則返回 false
。
在 JavaScript 中,邏輯運算符更加靈活強大。但是,首先讓我們看一下操作數(shù)是布爾值的時候發(fā)生了什么。
下面是四種可能的邏輯組合:
alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false
正如我們所見,除了兩個操作數(shù)都是 false
的情況,結果都是 true
。
如果操作數(shù)不是布爾值,那么它將會被轉化為布爾值來參與運算。
例如,數(shù)字 1
被作為 true
處理,數(shù)字 0
則被作為 false
:
if (1 || 0) { // 工作原理相當于 if( true || false )
alert( 'truthy!' );
}
大多數(shù)情況下,邏輯或 ||
會被用在 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.' ); // 是周末
}
上文提到的邏輯處理多少有些傳統(tǒng)了。下面讓我們看看 JavaScript 的“附加”特性。
拓展的算法如下所示。
給定多個參與或運算的值:
result = value1 || value2 || value3;
或運算符 ||
做了如下的事情:
true
?,就停止計算,返回這個操作數(shù)的初始值。false
?),則返回最后一個操作數(shù)。返回的值是操作數(shù)的初始形式,不會做布爾轉換。
換句話說,一個或運算 ?||
? 的鏈,將返回第一個真值,如果不存在真值,就返回該鏈的最后一個值。
例如:
alert( 1 || 0 ); // 1(1 是真值)
alert( null || 1 ); // 1(1 是第一個真值)
alert( null || 0 || 1 ); // 1(第一個真值)
alert( undefined || null || 0 ); // 0(都是假值,返回最后一個值)
與“純粹的、傳統(tǒng)的、僅僅處理布爾值的或運算”相比,這個規(guī)則就引起了一些很有趣的用法。
例如,我們有變量 firstName
、lastName
和 nickName
,都是可選的(即可以是 undefined,也可以是假值)。
我們用或運算 ||
來選擇有數(shù)據(jù)的那一個,并顯示出來(如果沒有設置,則用 "Anonymous"
):
let firstName = "";
let lastName = "";
let nickName = "SuperCoder";
alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
如果所有變量的值都為假,結果就是 "Anonymous"
。
或運算符 ||
的另一個用途是所謂的“短路求值”。
這指的是,||
對其參數(shù)進行處理,直到達到第一個真值,然后立即返回該值,而無需處理其他參數(shù)。
如果操作數(shù)不僅僅是一個值,而是一個有副作用的表達式,例如變量賦值或函數(shù)調(diào)用,那么這一特性的重要性就變得顯而易見了。
在下面這個例子中,只會打印第二條信息:
true || alert("not printed");
false || alert("printed");
在第一行中,或運算符 ||
在遇到 true
時立即停止運算,所以 alert
沒有運行。
有時,人們利用這個特性,只在左側的條件為假時才執(zhí)行命令。
兩個 & 符號表示 &&
與運算符:
result = a && b;
在傳統(tǒng)的編程中,當兩個操作數(shù)都是真值時,與運算返回 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' );
}
就像或運算一樣,與運算的操作數(shù)可以是任意類型的值:
if (1 && 0) { // 作為 true && false 來執(zhí)行
alert( "won't work, because the result is falsy" );
}
給出多個參加與運算的值:
result = value1 && value2 && value3;
與運算 &&
做了如下的事:
false
?,就停止計算,并返回這個操作數(shù)的初始值。換句話說,與運算返回第一個假值,如果沒有假值就返回最后一個值。
上面的規(guī)則和或運算很像。區(qū)別就是與運算返回第一個假值,而或運算返回第一個真值。
例如:
// 如果第一個操作數(shù)是真值,
// 與運算返回第二個操作數(shù):
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5
// 如果第一個操作數(shù)是假值,
// 與運算將直接返回它。第二個操作數(shù)會被忽略
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
我們也可以在一行代碼上串聯(lián)多個值。查看第一個假值是如何被返回的:
alert( 1 && 2 && null && 3 ); // null
如果所有的值都是真值,最后一個值將會被返回:
alert( 1 && 2 && 3 ); // 3,最后一個值
與運算 ?
>>
? 在或運算 ?||
? 之前進行與運算
&&
的優(yōu)先級比或運算||
要高。
所以代碼
a && b || c && d
跟&&
表達式加了括號完全一樣:(a && b) || (c && d)
。
不要用 ?
||
? 或 ?>>
? 來取代 ?if
?有時候,有人會將與運算符
&&
作為“簡化if
”的一種方式。
例如:
let x = 1; (x > 0) && alert( 'Greater than zero!' );
&&
右邊的代碼只有運算抵達到那里才能被執(zhí)行。也就是,當且僅當(x > 0)
為真。
所以我們基本可以類似地得到:
let x = 1; if (x > 0) alert( 'Greater than zero!' );
雖然使用
&&
寫出的變體看起來更短,但if
更明顯,并且往往更具可讀性。因此,我們建議根據(jù)每個語法結構的用途來使用:如果我們想要if
,就使用if
;如果我們想要邏輯與,就使用&&
。
感嘆符號 !
表示布爾非運算符。
語法相當簡單:
result = !value;
邏輯非運算符接受一個參數(shù),并按如下運作:
true/false
?。例如:
alert( !true ); // false
alert( !0 ); // true
兩個非運算 !!
有時候用來將某個值轉化為布爾類型:
alert( !!"non-empty string" ); // true
alert( !!null ); // false
也就是,第一個非運算將該值轉化為布爾類型并取反,第二個非運算再次取反。最后我們就得到了一個任意值到布爾值的轉化。
有一個略顯冗長的方式也可以實現(xiàn)同樣的效果 —— 一個內(nèi)建的 Boolean
函數(shù):
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
非運算符 !
的優(yōu)先級在所有邏輯運算符里面最高,所以它總是在 &&
和 ||
之前執(zhí)行。
重要程度: 5
如下代碼將會輸出什么?
alert( null || 2 || undefined );
結果是 2
,這是第一個真值。
alert( null || 2 || undefined );
重要程度: 3
下面的代碼將會輸出什么?
alert( alert(1) || 2 || alert(3) );
答案:首先是 1
,然后是 2
。
alert( alert(1) || 2 || alert(3) );
對 alert
的調(diào)用沒有返回值?;蛘哒f返回的是 undefined
。
||
? 對它的左值 ?alert(1)
? 進行了計算。這就顯示了第一條信息 ?1
?。alert
?返回了 ?undefined
?,所以或運算繼續(xù)檢查第二個操作數(shù)以尋找真值。2
? 是真值,所以執(zhí)行就中斷了。?2
? 被返回,并且被外層的 alert 顯示。這里不會顯示 ?3
?,因為運算沒有抵達 ?alert(3)
?。
重要程度: 5
下面這段代碼將會顯示什么?
alert( 1 && null && 2 );
答案:null
,因為它是列表中第一個假值。
alert(1 && null && 2);
重要程度: 3
這段代碼將會顯示什么?
alert( alert(1) && alert(2) );
答案:1
,然后 undefined
。
alert( alert(1) && alert(2) );
調(diào)用 alert
返回了 undefined
(它只展示消息,所以沒有有意義的返回值)。
因此,&&
計算了它左邊的操作數(shù)(顯示 1
),然后立即停止了,因為 undefined
是一個假值。&&
就是尋找假值然后返回它,所以運算結束。
重要程度: 5
結果將會是什么?
alert( null || 2 && 3 || 4 );
答案:3
。
alert( null || 2 && 3 || 4 );
與運算 &&
的優(yōu)先級比 ||
高,所以它第一個被執(zhí)行。
結果是 2 && 3 = 3
,所以表達式變成了:
null || 3 || 4
現(xiàn)在的結果就是第一個真值:3
。
重要程度: 3
寫一個 if
條件句來檢查 age
是否位于 14
到 90
的閉區(qū)間。
“閉區(qū)間”意味著,age
的值可以取 14
或 90
。
if (age >= 14 && age <= 90)
重要程度: 3
寫一個 if
條件句,檢查 age
是否不位于 14
到 90
的閉區(qū)間。
創(chuàng)建兩個表達式:第一個用非運算 !
,第二個不用。
第一個表達式:
if (!(age >= 14 && age <= 90))
第二個表達式:
if (age < 14 || age > 90)
重要程度: 5
下面哪一個 alert
將會被執(zhí)行?
if(...)
語句內(nèi)表達式的結果是什么?
if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );
答案:第一個和第三個將會被執(zhí)行。
詳解:
// 執(zhí)行。
// -1 || 0 的結果為 -1,真值
if (-1 || 0) alert( 'first' );
// 不執(zhí)行。
// -1 && 0 = 0,假值
if (-1 && 0) alert( 'second' );
// 執(zhí)行
// && 運算的優(yōu)先級比 || 高
// 所以 -1 && 1 先執(zhí)行,給出如下運算鏈:
// null || -1 && 1 -> null || 1 -> 1
if (null || -1 && 1) alert( 'third' );
重要程度: 3
實現(xiàn)使用 prompt
進行登錄校驗的代碼。
如果訪問者輸入 "Admin"
,那么使用 prompt
引導獲取密碼,如果輸入的用戶名為空或者按下了 ?Esc
? 鍵 —— 顯示 “Canceled”,如果是其他字符串 —— 顯示 “I don't know you”。
密碼的校驗規(guī)則如下:
流程圖:
請使用嵌套的 if
塊。注意代碼整體的可讀性。
提示:將空字符串輸入,prompt 會獲取到一個空字符串 ''
。Prompt 運行過程中,按下 ?ESC
? 鍵會得到 null
。
let userName = prompt("Who's there?", '');
if (userName === 'Admin') {
let pass = prompt('Password?', '');
if (pass === 'TheMaster') {
alert( 'Welcome!' );
} else if (pass === '' || pass === null) {
alert( 'Canceled' );
} else {
alert( 'Wrong password' );
}
} else if (userName === '' || userName === null) {
alert( 'Canceled' );
} else {
alert( "I don't know you" );
}
請注意 if
塊中水平方向的縮進。技術上是非必需的,但會提升代碼的可讀性。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: