ECMAScript 2020 支援了 ?. Optional Chaining Operator,至此 ECMAScript 終於有專屬的 Operator 用於 Nested Object,不必再借用 && 與 Falsy Value。
Version
ECMAScript 2020
Object
let book = {
title: 'FP in JavaScript',
price: {
amazon: 100
}
}
book.price.amazon // ?
book.fee.amazon // ?
當 Object 的 property 為 Object,若 property 不存在,會出現 undefined 的 runtime error,這在 ECMAScript 經常出現。

let book = {
title: 'FP in JavaScript',
price: {
amazon: 100
}
}
book.price && book.price.amazon // ?
book.fee && book.fee.amazon // ?
傳統會先使用 && 判斷 book.fee property 是否存在,若存在才讀取該 property。
如 fee property 根本不存在,則 && 右側不會執行,直接 short-circuiting 回傳 undefined。
但 && 其實是判斷 truthy value,而 1、non-empty string 與 true 皆是 truthy value,因此可能誤判,並不是最完美解法。

let book = {
title: 'FP in JavaScript',
price: {
amazon: 100
}
}
book.price?.amazon // ?
book.fee?.amazon // ?
ES2020 支援了 ?.,若 book.fee property 存在才會讀取 book.fee.amazon,否則直接回傳 undefined。
?. 只判斷 null 與 undefined 而非 truthy value,因此不用擔心誤判。

Expression
let book = {
title: 'FP in JavaScript',
price: {
amazon: 100
}
}
book.price?.['amazon'] // ?
book.fee?.['amazon'] // ?
?. 也可以在 [] 使用 expression,因此可使用 variable。

Array
let book = {
title: 'FP in JavaScript',
price: [100]
}
book.price?.[0] // ?
book.fee?.[0] // ?
若 Object 的 property 為 Array,且不確定 property 是否存在,也可使用 ?. 判斷。

Function
let book = {
title: 'FP in JavaScript',
price: 100,
getDescription: function() {
return `${this.title} : ${this.price}`
}
}
book.getDescription?.() // ?
book.showDescription?.() // ?
若不確定 getDescription() 是否存在於 book Object,可在 () 執行前加上 ?. 判斷,若存在才執行。

?. with ??
let book = {
title: 'FP in JavaScript',
price: {
amazon: 100
}
}
book.price?.amazon ?? 'N/A' // ?
book.fee?.amazon ?? 'N/A' // ?
?. 雖然好用,但可能回傳 undefined,因此可搭配 ?? 提供預設值。

Error.response
<template>
<div>
<button @click="onClick">Error.response</button>
<div>{{ message }}</div>
</div>
</template>
<script>
import axios from 'axios'
let fetchAPI = () => axios.get('http://localhost:3000/')
let onClick = function() {
fetchAPI()
.then(x => x.data)
.then(x => this.message = x)
.catch(e => console.log(e.response?.status??'404'))
}
export default {
name:'App',
data: () => ({
message: ''
}),
methods: {
onClick
}
}
</script>
14 行
fetchAPI()
.then(x => x.data)
.then(x => this.message = x)
.catch(e => console.log(e.response?.status??'404'))
若要讀取 HTTP status code,可在 .catch() 讀取 x.response.status,但問題是 response 並不是永遠存在,如斷網時,error object 並沒有 response Object。
- 可使用
?.判斷responseObject 是否存在,若存在則回傳statusproperty - 若
responseObject 不存在為undefined,可用??提供預設值404
Summary
object.value?.propobject.value?.[expr]object.value?.[index]object.func?.(args)
?. 可用於檢查 Object、Array 或 Function 是否存在。
Conclusion
?.為 ES2020 標準,目前 browser 都已支援可安心使用- Node 在 14 以上支援
?.,若要在 Quokka 使用必須搭配 Node 14 以上 ?.支援 short-circuiting,如?.左側是null或undefined,則?.右側將不會執行?.與??在實務上經常搭配使用,因為?.可能回傳undefined,??剛好替undefined提供預設值?.實務上最常用在Error.reponse,因為responseObject 並不是永遠存在,並搭配??提供預設值