【譯】Javascript中你需要知道的最出色的新特性:Optional Chaining

  • 2019 年 10 月 6 日
  • 筆記

對於使用Javascript的每個人來說,可選鏈(Optional chaining)是遊戲的規則的改變者。它與箭頭函數或let和const一樣重要。我們討論下它可以解決什麼問題,它如何工作,以及它如何使得你的生活更加輕鬆。

問題

想像以下場景:

你正在使用片段程式碼來從一個API載入數據。返回數據是深度嵌套的對象,這就意味著你需要遍歷很長的對象屬性。

// API response object  const person = {      details: {          name: {              firstName: "Michael",              lastName: "Lampe",          }      },      jobs: [          "Senior Full Stack Web Developer",          "Freelancer"      ]  }  // Getting the firstName  const personFirstName = person.details.name.firstName;

現在,保留這樣的程式碼也是不錯的。不過,有個更好的解決方法,如下:

// Checking if firstName exists  if( person &&      person.details &&      person.details.name ) {          const personFirstName = person.details.name.firstName || 'stranger';  }

正如示例中你所看到的,即使是簡單的事情,比如獲取一個人的名字,也很難正確獲取。

所以,這就是為什麼我們使用類似lodash庫去處理這樣的事情:

_.get(person, 'details.name.firstName', 'stranger');

lodash使得程式碼更具可讀性,但是你得在你的程式碼庫中引入很多的依賴。你需要更新它,然後,如果你在一個團隊中工作,你需要在團隊中推廣使用它。所以,這也不是一個理想的解決方案。

解決方案

可選鏈為這些(除了團隊的問題)提供了一個解決方案。

它是怎麼工作的

初次看到可選鏈的新語法,你可能會感到陌生,但是,幾分鐘後你會習慣它的。

const personFirstName = person?.details?.name?.firstName;

好了,現在你腦子可能有很多問號(雙關語義)。上面語法的?是個新的事物。這就是你要想想的地方了。在屬性前(原文應該改為屬性後比較準確)有?.,就是在問你屬性person存在嗎?或者,更加javascript的表達方式--person屬性的值是null或undefined嗎?如果是,將不會返回一個錯誤,而是返回undefined。所以personFirstName將返回undefined。對details?和name?會進行重複的詢問。如果任意一個的值為null或undefined,之後personFirstName都會返回undefined。這被稱為Short-circuiting(短路)。一旦javascript找到值為null或undefined,它就會短路並不會再深入查詢下去。

默認值

我們還需要學學Nullish coalescing operator(空位合併運算符)。好吧,這聽起來很難學。但是實際上,一點也不難。我們看看下面的例子:

const personFirstName = person?.details?.name?.firstName ?? 'stranger';

Nullish coalescing operator用??來表示。它也很容易去解讀。如果??左側返回的內容是undefined,那麼personFirstName會將??右側的值賦值給它。這太容易了。

動態屬性

有時候你需要獲取動態的值。它可能是一個數組的值,或者是一個對象的動態屬性。

const jobNumber = 1;  const secondJob = person?.jobs?.[jobNumber] ?? 'none';

這裡需要重點理解的地方是jobs?.[jobNumber],它和jobs[jobNumber]表達的一樣,但是不會拋出一個錯誤;相反,它會返回none值。

函數或方法調用

有時候,你會處理對象,而你不知道它們是否帶有方法。這裡我們可以使用?.()語法或帶參數?.({ some: 'args'})語法。它會根據你的需求運行。如果在那個對象中不存在這個方法,它會返回值undefined。

const currentJob = person?.jobs.getCurrentJob?.() ?? 'none';

上面的例子中,如果沒有getCurrentJob方法,那麼currentJob將會返回none。

今天開始使用它

目前沒有瀏覽器支援此功能--Babel做轉換了。

這裡已經有一個babel.js插件,如果你已經有了Babel設置,那就很容易集成了。

babel-plugin-proposal-optional-chaining

參考和後話

Tags: