JavaScript 問號配冒號、問號點、雙問號,是什麼意思?
第一次看到時頭上一堆問號,他們是做什麼的?
🕒 published on ー 2022. 1. 18.
🔁 last updated ー 2022. 1. 31.
Free Talk
曾遇過某前端主管認為寫 Lambda 就是很專業、Code 很乾淨、資深就一律應該直接寫 Lambda,
寫出 if ... else
,就是不專業、不夠格當資深。
嗯……… 窩不知道。
我知道的是,
- Lambda 真的好用方便又可讓 Code 少很多行,我也很愛用。
- 但這聽起來是 Coding style 的問題,應該跟 Clean code 是兩回事。
- 網頁前端寫的當然是 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();
Image by Chiyu
如果有人說:誰沒事會去用一個不存在的東西啊!都知道它不存在了還用,報錯不是剛好(等於等於臉)。
我會回:有沒有寫過前端啦 w!前端常常要告訴 React 等有東西的時候才渲染呀!API 回傳給前端的資料也常常會缺東缺西的呀!(可能後端那邊有別的考量,或本來就計畫好要前端利用缺東西這點做一些事)
現在寫 TypeScript,沒加個問號 TypeScript 也會給你畫條紅線,跟你說這個東西有可能會是 undefined 要注意呢!
雙問號 aka 空值合併運算子(Nullish Coalescing Operator)
這個也是跟問號點一起登場的新語法,但個人感覺還沒有很常見。
使用方法跟 ||
兩條直線(OR 運算子),是一模模一樣樣的,差別在 ??
只針對 null
跟 undefined
做事。
更精確點,兩條直線 return 它第一個遇到是 True 的東西;雙問號 return 它第一個遇到 有 defined 的東西。
// 用兩條直線,會得到右邊的值(數字0跟空字串會被當成 `False`)
const value1 = 0 || 'string';
const value2 = '' || 123;
// 用雙問號,會得到左邊的值(數字0跟空字串都算有 defined)
const value3 = 0 ?? 'string';
const value4 = '' ?? 123;
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;
那麼打完收工~!