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