前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >let { [key]: id = 0, ...rest } = obj-让解构发挥到极限

let { [key]: id = 0, ...rest } = obj-让解构发挥到极限

作者头像
六小登登
发布2019-08-14 11:31:30
4490
发布2019-08-14 11:31:30
举报
文章被收录于专栏:Modeng的专栏
知识共享许可协议
知识共享许可协议

版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

代码语言:javascript
复制

最近遇到了一个问题,来自于下面的一段代码:

代码语言:javascript
复制
let { [key]: id, ...rest } = obj

在这篇文章里,我想解释下它是在做什么以及它是如何工作的。

提醒:因为它非常的晦涩难懂,所以我最终并没有以这种方式实现去做,不过它是非常有趣的,值得去我们去了解。

如何遇到这个问题的

假如我们有以下数组

代码语言:javascript
复制
const users = [     { name: 'Michael', group: 1 },    { name: 'Lukas', group: 1 },    { name: 'Travis', group: 2 },]
    { name: 'Michael', group: 1 },
    { name: 'Lukas', group: 1 },
    { name: 'Travis', group: 2 },
]

我们把它按照 group 字段进行分组映射如下:

代码语言:javascript
复制
{    '1': [        { name: 'Michael' },        { name: 'Lukas' },    ],    '2': [        { name: 'Travis' },    ]}'1': [
        { name: 'Michael' },
        { name: 'Lukas' },
    ],
    '2': [
        { name: 'Travis' },
    ]
}

如何从 users 对象中删除 group 属性,实现上述效果?

我们可以利用如下方法:

代码语言:javascript
复制
users.reduce((result, user) => {  const { group, ...userData } = user  result[group] = result[group] || []  result[group].push(userData)  return result}, {})
  const { group, ...userData } = user
  result[group] = result[group] || []
  result[group].push(userData)

  return result
}, {})

这里用到了reduce 函数,如果不熟悉的同学,可以去查看相关资料就不多说了。

我的最终目标是使这个函数具有动态性,而现在是通过固定字段 group 来分组,并不是计算得来的。假如以后想使用其他字段进行分组就需要更改函数了。

在实现动态性之前我们先看看

代码语言:javascript
复制
const { group, ...userData } = user

因为它也是这篇文章我们想谈论的知识。

解构

上面的数据中每个用户都有 groupname 属性。因此在 ES6 中可以使用解构的方式获取对象中的值。

例如:

代码语言:javascript
复制
const { group } = user

它等效于

代码语言:javascript
复制
const group = user.group

还可以这么做

代码语言:javascript
复制
const { group, name } = user

它等效于

代码语言:javascript
复制
const group = user.groupconst name = user.name
const name = user.name

剩余参数

代码语言:javascript
复制
const { group, ...userData } = user

现在,这段代码有一个更复杂的问题需要我们讨论。

...userData 获取了除 group 之外的所有值,并把它们浅拷贝到一个新的常量 userData 中。在这种情况下 userData 变成一个仅有 name 属性的对象。

代码语言:javascript
复制
userData = {    name: "xx"}"xx"
}

在这里,我们不要混淆剩余参数和扩展运算,它们其实刚好是相反的。

代码语言:javascript
复制
const location = { country: 'Japan', city: 'Tokyo' }const newLocation = { ...location, zipcode: 123456 }//{country: "Japan", city: "Tokyo", zipcode: 123456}country: 'Japan', city: 'Tokyo' }

const newLocation = { ...location, zipcode: 123456 }
//{country: "Japan", city: "Tokyo", zipcode: 123456}

这里将会把 location 对象的属性全部展开,然后放入 newLocation 对象中。此时的 newLocation 对象将包含如下属性:

代码语言:javascript
复制
{country: "Japan", city: "Tokyo", zipcode: 123456}"Japan", city: "Tokyo", zipcode: 123456}

那么什么时候是「剩余参数」,什么时候是扩展运算?这将取决于赋值在哪边,在赋值左边的就是剩余参数,在赋值右边的就是扩展运算。

你也可以在函数中使用剩余参数

代码语言:javascript
复制
class BaseArray extends Array {    constructor(...values) { // rest        super(...values) // spread    }}
    constructor(...values) { // rest
        super(...values) // spread
    }
}

此时让我们来看看实现函数动态性的解决方案:

代码语言:javascript
复制
function groupBy(array, key) {    return array.reduce((result, item) => {        const { [key]: id, ...rest } = item        result[id] = result[id] || []        result[id].push(rest);        return result;    }, {})}
    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 之前,我们来看一个简单的例子。

分配新变量名

还记得这个吗?

代码语言:javascript
复制
const user = { group: 1 }const { group } = userconsole.log(group) //1group: 1 }
const { group } = user
console.log(group) //1

如果我们将 group 的值去转换为一个变量名为发生什么?我们可以这么做

代码语言:javascript
复制
const user = { group: 1 }const { group: id } = userconsole.log(id) //1group: 1 }
const { group: id } = user
console.log(id) //1

此时将会把 group 的值赋值给变量 id。

这实际上是非常有用的,因为有些时候对象的 key 作为变量名是无效的。

例如:

代码语言:javascript
复制
const foo = { 'fizz-buzz': true }const { 'fizz-buzz' } = foo 'fizz-buzz': true }
const { 'fizz-buzz' } = foo 

此时程序就会报错, 因为 fizz-buzz 不可以当作变量名使用。正确的写法如下:

代码语言:javascript
复制
const { 'fizz-buzz': fizzBuzz } = foo'fizz-buzz': fizzBuzz } = foo

那么我们该如何记住这个语法呢?其实是很简单的,这和我们创建对象时使用的是完全相同的语法。

代码语言:javascript
复制
const id = 1const user = {    group: id}1
const user = {
    group: id
}

因此,如果对象是在赋值(=)的右边,group 属性保存变量 id。

如果它是在赋值(=)的左边,它刚好是相反的。

代码语言:javascript
复制
const { group: id } = usergroup: id } = user

我们获取属性 group 的值,并将其放入变量 id 中。

最后,计算对象属性名

其他的都说完了,现在唯一解释的就剩下 [key].了。

我们可以使用它来访问计算属性名,在我们的例子中变量 key 的值是 group。

创建对象时如何添加计算 keys ?

使用相同的语法,只是它在赋值(=)的右边。

代码语言:javascript
复制
const key = 'group'const id = 1const user = {    [key]: id}'group'
const id = 1

const user = {
    [key]: id
}

但是如果我们只写 let { [key] } = obj 那么我们应该用什么名字来访问这个变量呢?我们是不能这样的。

因此,就像 fizz-buzz 一样,我们最终的方式就是:[key]: id

所以就是这样,我们还可以设置默认值应用于 id。

通常会是这样的

代码语言:javascript
复制
const user = { group: 1 }const { group = 0, createdAt = null} = usergroup: 1 }

const { group = 0, createdAt = null} = user

使用计算属性,它变成

代码语言:javascript
复制
let { [key]: id = 0, ...rest } = obj

原文:https://dev.to/mzanggl/let--key-id--0-rest---obj---destructuring-to-the-limit-deo 翻译:六小登登

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年08月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如何遇到这个问题的
  • 解构
  • 剩余参数
  • 分配新变量名
  • 最后,计算对象属性名
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档