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。
- 可使用
?.
判斷response
Object 是否存在,若存在則回傳status
property - 若
response
Object 不存在為undefined
,可用??
提供預設值404
Summary
object.value?.prop
object.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
,因為response
Object 並不是永遠存在,並搭配??
提供預設值