最近遇到了一個問題,來自於下面的一段代碼:javascript
let { [key]: id, ...rest } = obj
複製代碼
在這篇文章裏,我想解釋下它是在作什麼以及它是如何工做的。前端
提醒:由於它很是的晦澀難懂,因此我最終並無以這種方式實現去作,不過它是很是有趣的,值得去咱們去了解。java
假如咱們有如下數組git
const users = [
{ name: 'Michael', group: 1 },
{ name: 'Lukas', group: 1 },
{ name: 'Travis', group: 2 },
]
複製代碼
咱們把它按照 group
字段進行分組映射以下:github
{
'1': [
{ name: 'Michael' },
{ name: 'Lukas' },
],
'2': [
{ name: 'Travis' },
]
}
複製代碼
如何從 users
對象中刪除 group
屬性,實現上述效果?數組
咱們能夠利用以下方法:bash
users.reduce((result, user) => {
const { group, ...userData } = user
result[group] = result[group] || []
result[group].push(userData)
return result
}, {})
複製代碼
這裏用到了reduce
函數,若是不熟悉的同窗,能夠去查看相關資料就很少說了。函數
個人最終目標是使這個函數具備動態性,而如今是經過固定字段 group
來分組,並非計算得來的。假如之後想使用其餘字段進行分組就須要更改函數了。ui
在實現動態性以前咱們先看看spa
const { group, ...userData } = user
複製代碼
由於它也是這篇文章咱們想談論的知識。
上面的數據中每一個用戶都有 group
和 name
屬性。所以在 ES6 中可使用解構的方式獲取對象中的值。
例如:
const { group } = user
複製代碼
它等效於
const group = user.group
複製代碼
還能夠這麼作
const { group, name } = user
複製代碼
它等效於
const group = user.group
const name = user.name
複製代碼
const { group, ...userData } = user
複製代碼
如今,這段代碼有一個更復雜的問題須要咱們討論。
...userData
獲取了除 group
以外的全部值,並把它們淺拷貝到一個新的常量 userData
中。在這種狀況下 userData
變成一個僅有 name
屬性的對象。
userData = {
name: "xx"
}
複製代碼
在這裏,咱們不要混淆剩餘參數和擴展運算,它們其實恰好是相反的。
const location = { country: 'Japan', city: 'Tokyo' }
const newLocation = { ...location, zipcode: 123456 }
//{country: "Japan", city: "Tokyo", zipcode: 123456}
複製代碼
這裏將會把 location
對象的屬性所有展開,而後放入 newLocation
對象中。此時的 newLocation
對象將包含以下屬性:
{country: "Japan", city: "Tokyo", zipcode: 123456}
複製代碼
那麼何時是「剩餘參數」,何時是擴展運算?這將取決於賦值在哪邊,在賦值左邊的就是剩餘參數,在賦值右邊的就是擴展運算。
你也能夠在函數中使用剩餘參數
class BaseArray extends Array {
constructor(...values) { // rest
super(...values) // spread
}
}
複製代碼
此時讓咱們來看看實現函數動態性的解決方案:
function groupBy(array, key) {
return array.reduce((result, item) => {
const { [key]: id, ...rest } = item
result[id] = result[id] || []
result[id].push(rest);
return result;
}, {})
}
複製代碼
如今到底什麼是 const { [key]: id, ...rest } = item
?
咱們已經知道 ...rest
意味着什麼了。因此咱們就不說了。在解釋 [key]: id
以前,咱們來看一個簡單的例子。
還記得這個嗎?
const user = { group: 1 }
const { group } = user
console.log(group) //1
複製代碼
若是咱們將 group 的值去轉換爲一個變量名爲發生什麼?咱們能夠這麼作
const user = { group: 1 }
const { group: id } = user
console.log(id) //1
複製代碼
此時將會把 group 的值賦值給變量 id。
這其實是很是有用的,由於有些時候對象的 key
做爲變量名是無效的。
例如:
const foo = { 'fizz-buzz': true }
const { 'fizz-buzz' } = foo
複製代碼
此時程序就會報錯, 由於 fizz-buzz
不能夠看成變量名使用。正確的寫法以下:
const { 'fizz-buzz': fizzBuzz } = foo
複製代碼
那麼咱們該如何記住這個語法呢?實際上是很簡單的,這和咱們建立對象時使用的是徹底相同的語法。
const id = 1
const user = {
group: id
}
複製代碼
所以,若是對象是在賦值(=)的右邊,group 屬性保存變量 id。
若是它是在賦值(=)的左邊,它恰好是相反的。
const { group: id } = user
複製代碼
咱們獲取屬性 group 的值,並將其放入變量 id 中。
其餘的都說完了,如今惟一解釋的就剩下 [key].
了。
咱們可使用它來訪問計算屬性名,在咱們的例子中變量 key 的值是 group。
建立對象時如何添加計算 keys ?
使用相同的語法,只是它在賦值(=)的右邊。
const key = 'group'
const id = 1
const user = {
[key]: id
}
複製代碼
可是若是咱們只寫 let { [key] } = obj
那麼咱們應該用什麼名字來訪問這個變量呢?咱們是不能這樣的。
所以,就像 fizz-buzz
同樣,咱們最終的方式就是:[key]: id
。
因此就是這樣,咱們還能夠設置默認值應用於 id。
一般會是這樣的
const user = { group: 1 }
const { group = 0, createdAt = null} = user
複製代碼
使用計算屬性,它變成
let { [key]: id = 0, ...rest } = obj
複製代碼
原文:dev.to/mzanggl/let…
翻譯:六小登登
更多優質文章:六小登登的博客
我是:六小登登,一名愛寫做的技術人,從零開始自學前端,常活躍CSDN、掘金、公衆號等分享原創乾貨。 關注公衆號:六小登登,後臺回覆「1024」便可免費獲取驚喜福利!後臺回覆「加羣」羣裏天天都會全網蒐羅好文章給你。