iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
2
Modern Web

JavaScript基本功修煉系列 第 9

JavaScript基本功修練:Day9 - 短路求值與條件運算子的應用

  • 分享至 

  • xImage
  •  

承接昨天關於運算子的內容,今天會針對整理關於邏輯運算子和條件運算子的幾種用法。初學JavaScript的我,以為在if裏面才會用到&&||,甚至不知道有條件 ? 值1:值2??的寫法。直至遇上要為一個變數設定預設值,才知道可以用||

在這課題中,新手的我比較不熟悉的是:

  • 短路求值 (Short-circuit evaluation)
  • ?? 空值合併運算子(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""falsenullundefinedNaN都會是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? 除了undefinednull,其他都屬於defined。以下例子一目了然:

let price = 0;
console.log(price || 100); //100
console.log(price ?? 100); //0

??的世界中,只要不是nullundefined,條件就能成立。

條件?值1:值2 (條件運算子)

條件運算子比較特別是用到三個運算元,因此被稱為三元運算子。條件?值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
  • 條件運算子裏面可再包一個條件運算子
  • 條件運算子裏可以執行多個動作

雖然以上這些語法較簡潔和帥(?),不用每次都ifif去,但如果需要寫的功能較複雜,硬要用這些簡潔的寫法也可能會降低了可讀性,所以耍帥也要有限度,還是要按情況去用~

参考資料

Javascript 基礎打底系列 (三) - 邏輯運算子,與短路邏輯 (short circuit logic)
JAVASCRIPT.INFO - Nullish coalescing operator '??'
JavaScript — The Conditional (Ternary) Operator Explained


上一篇
JavaScript基本功修練:Day8 - 算術運算子、賦值運算子、比較運算子
下一篇
JavaScript基本功修練:Day10 - for、for與while的差別、do while、break、continue
系列文
JavaScript基本功修煉31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言