let { [key]: id = 0, ...rest } = obj-让解构发挥到极限
最近遇到了一个问题,来自于下面的一段代码:
let { [key]: id, ...rest } = obj
在这篇文章里,我想解释下它是在做什么以及它是如何工作的。
提醒:因为它非常的晦涩难懂,所以我最终并没有以这种方式实现去做,不过它是非常有趣的,值得去我们去了解。
如何遇到这个问题的
假如我们有以下数组
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
字段进行分组映射如下:
{ '1': [ { name: 'Michael' }, { name: 'Lukas' }, ], '2': [ { name: 'Travis' }, ]}'1': [ { name: 'Michael' }, { name: 'Lukas' }, ], '2': [ { name: 'Travis' }, ]}
如何从 users
对象中删除 group
属性,实现上述效果?
我们可以利用如下方法:
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
来分组,并不是计算得来的。假如以后想使用其他字段进行分组就需要更改函数了。
在实现动态性之前我们先看看
const { group, ...userData } = user
因为它也是这篇文章我们想谈论的知识。
解构
上面的数据中每个用户都有 group
和 name
属性。因此在 ES6 中可以使用解构的方式获取对象中的值。
例如:
const { group } = user
它等效于
const group = user.group
还可以这么做
const { group, name } = user
它等效于
const group = user.groupconst name = user.nameconst name = user.name
剩余参数
const { group, ...userData } = user
现在,这段代码有一个更复杂的问题需要我们讨论。
...userData
获取了除 group
之外的所有值,并把它们浅拷贝到一个新的常量 userData
中。在这种情况下 userData
变成一个仅有 name
属性的对象。
userData = { name: "xx"}"xx"}
在这里,我们不要混淆剩余参数和扩展运算,它们其实刚好是相反的。
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
对象将包含如下属性:
{country: "Japan", city: "Tokyo", zipcode: 123456}"Japan", city: "Tokyo", zipcode: 123456}
那么什么时候是「剩余参数」,什么时候是扩展运算?这将取决于赋值在哪边,在赋值左边的就是剩余参数,在赋值右边的就是扩展运算。
你也可以在函数中使用剩余参数
class BaseArray extends Array { constructor(...values) { // rest super(...values) // spread }} 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; }, {})} 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 } = userconsole.log(group) //1group: 1 }const { group } = userconsole.log(group) //1
如果我们将 group 的值去转换为一个变量名为发生什么?我们可以这么做
const user = { group: 1 }const { group: id } = userconsole.log(id) //1group: 1 }const { group: id } = userconsole.log(id) //1
此时将会把 group 的值赋值给变量 id。
这实际上是非常有用的,因为有些时候对象的 key
作为变量名是无效的。
例如:
const foo = { 'fizz-buzz': true }const { 'fizz-buzz' } = foo 'fizz-buzz': true }const { 'fizz-buzz' } = foo
此时程序就会报错, 因为 fizz-buzz
不可以当作变量名使用。正确的写法如下:
const { 'fizz-buzz': fizzBuzz } = foo'fizz-buzz': fizzBuzz } = foo
那么我们该如何记住这个语法呢?其实是很简单的,这和我们创建对象时使用的是完全相同的语法。
const id = 1const user = { group: id}1const user = { group: id}
因此,如果对象是在赋值(=)的右边,group 属性保存变量 id。
如果它是在赋值(=)的左边,它刚好是相反的。
const { group: id } = usergroup: id } = user
我们获取属性 group 的值,并将其放入变量 id 中。
最后,计算对象属性名
其他的都说完了,现在唯一解释的就剩下 [key].
了。
我们可以使用它来访问计算属性名,在我们的例子中变量 key 的值是 group。
创建对象时如何添加计算 keys ?
使用相同的语法,只是它在赋值(=)的右边。
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。
通常会是这样的
const user = { group: 1 }const { group = 0, createdAt = null} = usergroup: 1 }
const { group = 0, createdAt = null} = user
使用计算属性,它变成
let { [key]: id = 0, ...rest } = obj
原文:https://dev.to/mzanggl/let--key-id--0-rest---obj---destructuring-to-the-limit-deo
翻译:六小登登
我是:六小登登,一名爱写作的技术人,从零开始自学前端,常活跃CSDN、掘金、公众号等分享原创干货。
关注公众号:六小登登,后台回复「1024」即可免费获取惊喜福利!后台回复「加群」群里每天都会全网搜罗好文章给你。
上文:《90单身原因TOP3》
推荐:《Javascript中你必须理解的执行上下文和调用栈》
let { [key]: id = 0, ...rest } = obj-让解构发挥到极限相关推荐
- UE4之Obj模型解构解析
由于需求,必须研究obj模型的结构. 参考: Wavefront OBJ 英文文档 Warefront Object File (.obj)文档 obj + mtl 格式 三维模型obj文件的格式解析 ...
- 20181210-es6(letconst解构模版字符串原理 展开运算符、剩余运算符运用 深拷贝原理 reduce原理 箭头函数)...
变量声明 var 特点: 1.可以重复声明 2.不能定义常量 3.不支持块级作用域 复制代码 let //1.不存在预解释 变量提升 //2.暂时性死区 //3.具备块级,同一块内不能重复声明;let ...
- 前端学习必备之ES6解构赋值的常见用法
1.解构赋值可以轻松获取对象或者数组中的数据 var jsonData = {data: "111",data2: ["test","test2&qu ...
- ECMAScript 6入门 - 变量的解构赋值
定义 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 解构赋值不仅适用于var命令,也适用于let和const命令. 解构赋值的规则是,只要 ...
- es6学习 -- 解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前,为变量赋值,只能直接指定值. let a = 1; let b = 2; let c ...
- JavaScript学习笔记 -- ES6学习(三) 变量的解构赋值
1.解构赋值的定义 在ES6中,允许按照一定模式,从数组和对象中提取值(所谓解构),然后对变量进行赋值. var a = 1; var b = 2; var c = 3;//等价于var [a, b, ...
- exec 直接赋值_了解 JavaScript 解构赋值
引言 数组和对象就像一个 "压缩包". 在需要单独引用数组中的某一个元素时,解构赋值可以很方便的完成这个任务,它可以将数组和对象整体 "解压缩" 到一堆变量上, ...
- ES6解构赋值: ES6...转为ES5的写法
es6的特性,主要用于 数组和对象的析构 直接上问题: 因为chrome低版本(用的55版本)不支持es6...的下面这种写法, 需要转为es5写法 function calcLinePaths() ...
- 解构赋值(Destructuring)
解构赋值(Destructuring) ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 数组的解构赋值 以前,为变量赋值,只能直接指定值. ...
最新文章
- [转]Asp.Net 上传大文件专题(3)--从请求流中获取数据并保存为文件[下]
- 基于ArduinoLeonardo板子的BadUSB攻击实战
- python画出的雷达图效果-PYTHON绘制雷达图代码实例
- 由浅入深:自己动手开发模板引擎——置换型模板引擎(四)
- DDoS攻击的大量增加给企业带来了新的威胁——Vecloud
- IntelliJ IDEA 添加项目后编译显示包不存在的解决方案
- 腕上“小型手机”!小米手表万事俱备 坐等发布
- 在提交消息中链接到GitHub上的问题编号
- 微信接口开发之高级篇系列【网页授权获取用户基本信息】
- 一篇文章带你搞懂 SpringBoot与Swagger整合
- mysql可视化工具
- Rasa对话机器人连载一 第121课:Rasa对话机器人Debugging项目实战之电商零售对话机器人运行流程调试全程演示-1
- 微信小程序开发之路(3)— 添加一个Button按钮点击事件
- oracle数据库快速查询关键字,数据库分页查询关键字
- flink watermark 生成机制与总结
- 网络安全-使用PGP实现电子邮件安全
- 【R_绘图】绘图字体设为Times New Roman
- 京东超级秒杀时间html,京东418超级秒杀节LOGO及使用规范
- nested exception is org.apache.ibatis.binding.BindingException: Parameter ‘email‘ not found. Availab
- 转:Jenkins+Jmeter+ant接口自动化框架for Linux学习
热门文章
- C++ 输入年月,打印出这个月的日历
- 计算机模拟comsol,基于COMSOL固体氧化物燃料电池(SOFC)的数值模拟仿真
- matlab调幅举例,基于MATLAB的单边带调幅和解调的实现设计.doc
- 慕尼黑计算机学院大旋梯,欧洲四国自由行(7)--德国佛莱堡/新天鹅堡/慕尼黑/柏林...
- 视频实例分割paper(一)《Video Instance Segmentation》
- 操作电脑:谨防“腕管综合症”
- 【微信小程序】--WXML WXSS JS 逻辑交互介绍(四)
- Java 实现长图文生成
- 关于计算机技术的英文,关于计算机技术在教育中的多方应用 中英文对照.doc
- 机械结构工程师的日常