Blog
Blog copied to clipboard
[MDN] Optional chaining
Optional chaining
-
Optional chaining 運算子(
?.
) 是讀取物件底層的屬性值, 但不需要明確驗證每個 chaining 的參考都合法. 功能相似於.
chaining 運算子, 若參考是nullish
(null
或undefined
) 會造成錯誤, 而?.
會 short-circuits 運算回傳undefined
. 如果用於函式呼叫且不存在, 則回傳undefined
.
語法
obj.val?.prop
obj.val?.[expr]
obj.arr?.[index]
obj.func?.(args)
說明
- 當參考或函式可能是
undefined
或null
時, 簡化存取數值.
let nestedProp = obj.first && obj.first.second;
- 存取
obj.first.second
前, 會確認obj.first
不是null
(且不是undefined
).
let nestedProp = obj.first?.second;
// 相當於
let temp = obj.first;
let nestedProp = temp === null || temp === undefined ? undefined : temp.second;
用於函式呼叫
let result = someInterface.customMethod?.();
注意: 如果屬性不是函式, 使用
?.
仍然有TypeError
的例外(someInterface 的 customMethod 不是函式
).
注意: 若
someInterface
本身是null
或undefined
, 仍然有TypeError
(someInterface 是 null
). 如果預期someInterface
可能是null
或undefined
, 必須也使用?.
:
someInterface?.customMethod?.()
用於 callback 或事件處理
// ES2019 的寫法
function doSomething(onContent, onError) {
try {
// ... 做一些跟資料有關的事情
} catch (err) {
if (onError) {
// 測試 onError 是否真的存在
onError(err.message);
}
}
}
// 與函式呼叫使用可選串聯
function doSomething(onContent, onError) {
try {
// ... 做一些跟資料有關的事情
} catch (err) {
onError?.(err.message); // 如果 onError 是 undefined, 不會有例外
}
}
用於運算式
- 還可以用運算式存取屬性.
let nestedProp = obj?.["prop" + "Name"];
不可用於 =
的左側
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
用於存取陣列項目
let arrayItem = arr?.[42];
範例
基本範例
let myMap = new Map();
myMap.set("foo", { name: "baz", desc: "inga" });
let nameBar = myMap.get("bar")?.name;
Short Circuits 求值
- 若左側運算元是
null
或undefined
, 則運算式不會求值. 舉例:
let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // 0 因為 x 沒有累加
用於巢狀結構
let customer = {
name: "Carl",
details: {
age: 82,
location: "Paradise Falls", // 未知的詳細地址
},
};
let customerCity = customer.details?.address?.city;
let customerName = customer.name?.getName?.(); // 方法不存在
組合使用
- 當找不到時, 要給預設值.
let customer = {
name: "Carl",
details: { age: 82 },
};
const customerCity = customer?.city ?? "未知城市";
console.log(customerCity); // 未知城市
瀏覽器相容
- 除了 IE, 手持的 Opera Android 和 Samsung Internet 以外都支援.