【譯】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