TypeScript 中 Optional Chaining 和 Nullish Coalescing

劉哇勇發表於2021-05-25

Optional Chaining 解決的問題是重複且無意義的判空,之所以說無意義,是對業務來說它不是必需的,但不判空,程式直接就掛了,比如:

let x = foo.bar.baz();
 

這裡的訪問鏈路上 foo bar baz 任何一個為 undefined,程式就停止工作。

使用 Optional Chaining 修改後:

let x = foo?.bar.baz();
 

這裡 ?. 的句法就是 Optional Chaining,在 TypeScript 3.7 中實現,目前 tc39 提案中處於 Stage 4 階段。

Optional Chaining 在這裡表示,如果 foonullundefined,整個語句不繼續往後執行,直接返回 undefined

作用範圍

需要注意的是,這裡只對 foo 進行了保障,如果後續的 barbaz 為空的話,程式碼仍然報錯。?. 只作用於左邊的物件。

所以可以這樣來修正:

let x = foo?.bar?.baz();
 

這樣可以保障 foo bar 為空的情況下不報錯。這體現了 optional property accesses 的功能。

Opptoinal call

對於方法也同樣適用。

async function makeRequest(url: string, log?: (msg: string) => void) {
  log?.(`Request started at ${new Date().toISOString()}`);
  // roughly equivalent to
  //   if (log != null) {
  //       log(`Request started at ${new Date().toISOString()}`);
  //   }

  const result = (await fetch(url)).json();

  log?.(`Request finished at at ${new Date().toISOString()}`);

  return result;
}
 

Optional element access

陣列也是物件,只不是特殊的物件,通過數字索引作為屬性來訪問。所以 Optional Chaining 也可作用於陣列元素的訪問,此時就體現了 optional element access 的功能,請看來自官方文件中的示例:

/**
 * Get the first element of the array if we have an array.
 * Otherwise return undefined.
 */
function tryGetFirstElement<T>(arr?: T[]) {
  return arr?.[0];
  // equivalent to
  //   return (arr === null || arr === undefined) ?
  //       undefined :
  //       arr[0];
}
 

&& 的差別

雖說 Optional Chaining 取代瞭如下通過 && 來實現的判空操作:

// Before
if (foo && foo.bar && foo.bar.baz) {
  // ...
}
 

但 Optional Chaining 和 && 還是有區別,後者利用 JavaScript 中的短路機制,遇到假值時中斷執行。而前者只會在被判定物件為 nullundefined 時才會中斷執行。

請看如下示例:

const a: any = 0;
console.log(a?.blah);
console.log(a && a.blah);

const b: any = false;
console.log(b?.blah);
console.log(b && b.blah);

const c: any = "";
console.log(c?.blah);
console.log(c && c.blah);
 

輸出:

undefined
0
undefined
false
undefined

 

可以看到,通過 Optional Chaining 控制的部分全部輸出 undefined,因為這裡被判定物件並不是 nullundefined,所以語句會往後執行,嘗試訪問 blah,拿到的值是 undefined,最後輸出。

而通過 && 進行判定的語句,因為被判定物件是假值,中斷執行並返回當前物件。

Nullish Coalescing

Nullish Coalescing 通過 ?? 操作符,為 nullundefined 的值提供預設值。

比如:

let x = foo ?? bar();
 

上面的表示式等價於如果 foonullundefined,則呼叫 bar()

同樣地,他取代了之前通過 || 操作符達到的預設值效果,但後者同樣是通過判斷布林真值達到的,而 Nullish Coalescing 只判斷 nullundefined

比如:

function initializeAudio() {
  let volume = localStorage.volume || 0.5;

  // ...
}
 

這裡如果 localStorage.volume 被設定成 0,則最後 volume 得到的是 0.5,也就是說設定在 localStorage.volume 永遠也不會生效。而 Nullish Coalescing 就可以避免這種問題。

相關資源

The text was updated successfully, but these errors were encountered:

相關文章