承接昨天關於運算子的內容,今天會針對整理關於邏輯運算子和條件運算子的幾種用法。初學JavaScript的我,以為在if
裏面才會用到&&
和||
,甚至不知道有條件 ? 值1:值2
和??
的寫法。直至遇上要為一個變數設定預設值,才知道可以用||
。
在這課題中,新手的我比較不熟悉的是:
??
空值合併運算子(Nullish coalescing operator)條式 ? 值1 : 值2
條件運算子(Conditional (ternary) operator)短路求值(Short-circuit evaluation)是指一種方法,它是指用||
或&&
來寫比起if
判斷式更短更簡潔的判斷式。一開始學JS時,只懂在if else
判斷式裏面用||
和&&
,但之後發現它們其實還有更多用法,例如:
||
設定預設值&&
檢查物件屬性是否存在,如果存在才去執行後面的動作||
設定預設值重溫||
(or)的特性:
只要其中一個條件是true
,就會返回true
。換句話說,只要有一邊的條件被滿足,就會成立。如下面例子:
ture || true //true
true || false //true
false || false //false
true || 3==4 //true
除了可以回傳布林值,也可以返回其他型別的值:
'apple' || true //'apple'
'apple' || 'orange' //'apple'
true || 'hello' //true
3==4 || 'apple' //'apple'
如果兩邊都是true
,就會返回第一個值。
那麼||
與預設值有什麼關係?看看維基百科的解釋:
短路求值是一種邏輯運算子的求值策略。只有當第一個運算數的值無法確定邏輯運算的結果時,才對第二個運算數進行求值。
利用||
的特性,我們可以在宣告變數時,賦予變數預設值,而不需要用if else
判斷式。例如以下的例子,假設我不能確定data
是否存在,我可以這樣寫:
var data = data || {}
以上的做法,意思就是如果data
這個變數值存在,就返回data
,否則就賦予{}
空物件。
在JavaScript中,0
、""
、false
、null
、undefined
和NaN
都會是false
(falsy)。按這個規則,以上的例子中,如果data
這個變數沒有值(undefined
),或者是空的值(例如null
、空字串等),data
就會變成false
,從而返回{}
空物件。這就是為不確定是否存在的變數,賦予預設值的意思。
其實用if
的寫法也行,但不如||
寫法一樣簡潔:
if (!data){
data = {}
}
再舉一個例子,如果用戶沒有輸入地址,就顯示為'unknown'
:
var user1 = {
name: 'Peter',
age: 20,
address: ""
}
var user2 = {
name: 'Mary',
age: 30,
address: "10/F, abc street, Kowloon, Hong Kong"
}
function showAddress(userInfo){
userAddress = userInfo.address || 'unknown'
console.log(`${userInfo.name}'s address is ${userAddress}.`)
//Peter's address is unknown.
//Mary's address is 10/F, abc street, Kowloon, Hong Kong.
}
showAddress(user1);
showAddress(user2);
另一個經常會用到預設值的例子就是撈取localStorage
的資料,例如todo list例子中,如果用戶瀏覽器localStorge
有儲存資料,我們就可以撈取來用,但如果沒有(即是用戶是第一次打開和使用這個網頁),我們就先賦予空值,使之後的程式碼可以把用戶輸入的待辦事項加進去,再把它存到localStorage
裏。
var data = JSON.parse(localStorage.getItem('toDo'))||[];
&&
檢查物件屬性是否存在&&
(and)是指只要有一個false
就不會成立。我們也可以理解為:如果第一個條件成立,才會繼續執行後面的程式碼,這個道理跟if
判斷式是一樣的,例如:
const customer = {
name: 'Tom',
city: 'Hong Kong',
//假設這個顧客沒有買任何商品
// cart: ['iPhone','MacBook']
}
customer.cart && console.log(`你的商品數量:${customer["cart"].length}`)
以上的例子,假設我們不確定顧客有沒有買任何商品,所以不確定物件裏是否有cart
這個屬性。&&
的規則是如果第一個條件成立,才會繼續執行後面的程式碼,因此物件如果沒有cart
屬性,就不會執行後面用console
顯示商品數量訊息的程式碼。
這樣的寫法,用if
去寫當然也行:
if(customer.cart){
console.log(`你的商品數量:${customer["cart"].length}`)
}
??
的用法與||
的用法非常相似,都能用作預設值,差異之處是:
??
會返回第一個defined
的值||
會返回第一個truthy
的值何為defined
? 除了undefined
和null
,其他都屬於defined
。以下例子一目了然:
let price = 0;
console.log(price || 100); //100
console.log(price ?? 100); //0
在??
的世界中,只要不是null
或undefined
,條件就能成立。
條件運算子比較特別是用到三個運算元,因此被稱為三元運算子。在條件?值1:值2
的語法中,如果條件
成立,就返回值1
,不成立就返回值2
。
舉個簡單例子:
let user = {
name: 'John',
age: 23,
driving: null
}
user.driving = user.age >= 18 ? 'Allowed' : 'Not allowed'
console.log(user); //{name: "John", age: 23, driving: "Allowed"}
等同以下if
寫法:
if(user.age >= 18){
user.driving = 'Allowed'
}else{
user.driving = 'Not Allowed'
}
好像懂了?再看看以下較複雜的例子:
let university = false;
let workingYears = 3;
let jobOffer = university ? true : workingYears > 2 ? true : false
console.log(jobOffer) //true
假設有公司的應徵要求是要持有大學學位就行,如沒有的話,申請人就需要有多於2年的工作經驗,我們就可以包多一個條件運算子再裏面去做判斷,變成:
除此之外,我們也可以在條件運算式裏執行其他動作:
let interviewResult = false;
let jobOffer = null;
interviewResult ? (
jobOffer = true,
console.log('Welcome to our company!')
) : (
console.log('Thank you for applying the job position!')
)
找工作真的是過五關斬六將QQ,這個例子就是通過面試才會顯示歡迎加入公司的訊息,否則就只有感謝訊息。
短路求值應用例子:
||
設定預設值&&
檢查物件屬性是否存在,如果存在才去執行後面的動作?? (空值合併運算子):
||
的作用一樣??
會返回第一個defined的值||
會返回第一個truthy的值條件?值1:值2(條件運算子):
條件
成立,就返回值1
,不成立就返回值2
雖然以上這些語法較簡潔和帥(?),不用每次都if
來if
去,但如果需要寫的功能較複雜,硬要用這些簡潔的寫法也可能會降低了可讀性,所以耍帥也要有限度,還是要按情況去用~
Javascript 基礎打底系列 (三) - 邏輯運算子,與短路邏輯 (short circuit logic)
JAVASCRIPT.INFO - Nullish coalescing operator '??'
JavaScript — The Conditional (Ternary) Operator Explained