對於使用Javascript
的每一個人來講,可選鏈(Optional chaining)是遊戲的規則的改變者。它與箭頭函數或let
和const
同樣重要。咱們討論下它能夠解決什麼問題,它如何工做,以及它如何使得你的生活更加輕鬆。javascript
想象如下場景:java
你正在使用片斷代碼來從一個API
加載數據。返回數據是深度嵌套的對象,這就意味着你須要遍歷很長的對象屬性。git
// 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;
複製代碼
如今,保留這樣的代碼也是不錯的。不過,有個更好的解決方法,以下:github
// Checking if firstName exists
if( person &&
person.details &&
person.details.name ) {
const personFirstName = person.details.name.firstName || 'stranger';
}
複製代碼
正如示例中你所看到的,即便是簡單的事情,好比獲取一我的的名字,也很難正確獲取。web
因此,這就是爲何咱們使用相似lodash
庫去處理這樣的事情:數組
_.get(person, 'details.name.firstName', 'stranger');
複製代碼
lodash
使得代碼更具可讀性,可是你得在你的代碼庫中引入不少的依賴。你須要更新它,而後,若是你在一個團隊中工做,你須要在團隊中推廣使用它。因此,這也不是一個理想的解決方案。瀏覽器
可選鏈爲這些(除了團隊的問題)提供了一個解決方案。babel
初次看到可選鏈的新語法,你可能會感到陌生,可是,幾分鐘後你會習慣它的。函數
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
,它就會短路並不會再深刻查詢下去。ui
咱們還須要學學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