logo-Chiyu

Chiyu

Blog

Here I share my stories.

JavaScript 問號配冒號、問號點、雙問號,是什麼意思?

第一次看到時頭上一堆問號,他們是做什麼的?

🕒 published on ー 2022. 1. 18.

🔁 last updated ー 2022. 1. 31.

thumbnail.png

Photo by Dan Gold on Unsplash

Free Talk

曾遇過某前端主管認為寫 Lambda 就是很專業、Code 很乾淨、資深就一律應該直接寫 Lambda, 寫出 if ... else,就是不專業、不夠格當資深。

嗯……… 窩不知道。

我知道的是,

  1. Lambda 真的好用方便又可讓 Code 少很多行,我也很愛用。
  2. 但這聽起來是 Coding style 的問題,應該跟 Clean code 是兩回事。
  3. 網頁前端寫的當然是 JavaScript;JS 開始能寫 Lambda 語法糖 基本也是 ES6 以後了說。

Coding style 固然能作為評斷一個人是否專業、夠格當資深的一個項目,但也不至於到說「喔你沒用某某語法你不專業你不資深!」這麼的…一竿子打翻一艘船吧。

問號配冒號 aka 條件運算子(Conditional Operator)

這在寫 React、styled-components 的時候真的很方便也不難懂。也有人稱是 三元(Ternary) 運算子,不是那個一二三三原 w

條件 ? if True 要做的事 : if False 要做的事

/* 如果 score 小於 60 是 true,
   就 return 'red'(color 就會是紅色),
   否則 return 'black'(color 就會是黑色)。*/
const color = score < 60 ? 'red' : 'black';

// 用平常的 if ... else 寫
let color;
if (score < 60) {
  coloe = 'red';
} else {
  color = 'black';
}

無非就是 if ... else 的簡化。冒號左右兩邊 Code 較多想斷行,比照平常 return 東西的寫法就行。

似乎太簡單?那就來看辣個經典的 Google 面試題 FizzBuzz,也可以這樣寫呀:

/* 如果 i 能被 15 整除(是 15 的倍數),印 'FizzBuzz',
   否則如果 i 能被 5 整除(是 5 的倍數),印 'Buzz',
   再否則如果 i 能被 3 整除(是 3 的倍數),印 'Fizz' */
for (let i = 1; i <= n; i++) {
  i % 15 === 0 ? console.log('FizzBuzz') : i % 5 === 0 ? console.log('Buzz') : i % 3 === 0 && console.log('Fizz');
}

用什麼方法解題非本篇重點,就寫了可說是最無腦的範例(i % 15 === 0 其實非必要能再優化,也有不用 % 更有效率的解法,還有其實問號、冒號後也可以斷行 + 縮排會較好讀), 這個範例應該能感受到我所謂的不難懂 XD

問號點 aka 可選串連運算子(Optional Chaining Operator)

這個可是 2020 年才正式問世的,也是很方便好用。假設我們有個物件如下:

const student = {
  name: 'Aoi',
  age: 16,
};

此時,若我們取用一個不存在於 student 的東西,用 普通的點 跟用 問號點 的差別:

// 報錯,然後程式就停住不跑了。
student.write.score();

// 會 return undefined,不會報錯、程式會繼續跑
student.write?.score();
optional-chaining.png

Image by Chiyu

如果有人說:誰沒事會去用一個不存在的東西啊!都知道它不存在了還用,報錯不是剛好(等於等於臉)。

我會回:有沒有寫過前端啦 w!前端常常要告訴 React 等有東西的時候才渲染呀!API 回傳給前端的資料也常常會缺東缺西的呀!(可能後端那邊有別的考量,或本來就計畫好要前端利用缺東西這點做一些事)

現在寫 TypeScript,沒加個問號 TypeScript 也會給你畫條紅線,跟你說這個東西有可能會是 undefined 要注意呢!

雙問號 aka 空值合併運算子(Nullish Coalescing Operator)

這個也是跟問號點一起登場的新語法,但個人感覺還沒有很常見。 使用方法跟 || 兩條直線(OR 運算子),是一模模一樣樣的,差別在 ?? 只針對 nullundefined 做事。

更精確點,兩條直線 return 它第一個遇到是 True 的東西;雙問號 return 它第一個遇到 有 defined 的東西。

// 用兩條直線,會得到右邊的值(數字0跟空字串會被當成 `False`)
const value1 = 0 || 'string';
const value2 = '' || 123;

// 用雙問號,會得到左邊的值(數字0跟空字串都算有 defined)
const value3 = 0 ?? 'string';
const value4 = '' ?? 123;
nullish-coalescing.png

Image by Chiyu

如果有 抓不到東西的話,也要回傳一個預設值 的需求,就可以用雙問號唷!

Ending

所以,能怎樣在 React 裡(React Hooks + Functional Component)使用這些問號文?來個問號配冒號以及問號點併用的範例吧!

const MyComponent = () => {
  // 假設要在 Component Did Mount 時從 API 那讀取一些資料
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('My API Url.');
        const json = await response.json();
        setData(json);
      } catch (error) {
        console.error(error);
      }
    };
    fetchData();
  }, []);

  // 運用條件運算子跟可選串連來做條件渲染
  return <div>{data?.length > 0 ? <h1>{data[0]['title']}</h1> : <div>{`Loading...`}</div>}</div>;
};

export default MyComponent;

那麼打完收工~!

Copyright © 2022 Chiyu