符号 ... 在 JS 语言里同时被用作 Rest 与 Spread 两个场景,本周咱们就联合 Rest vs Spread syntax in JavaScript 聊聊这两者的差别以及一些坑。

概述

Spread

... 作为 Spread 含意时,成果为扩散对象的属性:

const obj = {  a: 1,  b: 2,  c: 3,};const newObj = {  ...obj,};console.log(newObj);// { a: 1, b: 2, c: 3 }

... 符号很形象的示意了把对象中所有属性拿进去平铺的含意。说到平铺,Spread 放在函数参数时,也示意将对象中每个 properties 拿进去作为平铺参数:

const arr = [1, 2, 3];const sum = (a, b, c) => a + b + c;console.log(sum(...arr)); // Outputs: 6//                 ^//          sum(1, 2, 3)

Rest

... 作 Rest 含意时,示意将多个值收集为一个数组,如用在函数定义的地位:

const sum = (...args) => {  return args.reduce((acc, curr) => acc + curr, 0);  //      ^  //  [1, 2, 3]};console.log(sum(1, 2, 3));// 6

当然也能够在 ... 后面搁置其余变量,这样 ... 仅聚合残余的变量。... 之后不能再定义变量或者 ...

const sum = (a, b, ...restOfArguments) => {  return a + b + restOfArguments.reduce((acc, curr) => acc + curr, 0);  //     ^   ^          ^  //     1   2      [3, 4, 5]};console.log(sum(1, 2, 3, 4, 5));// 15

精读

Rest 解决 Set 与 Map

SetMap 都能够通过数组模式赋初值:

const mySet = new Set(["a", "b", "c"]);const myMap = new Map([  ["a", 1],  ["b", 2],  ["c", 3],]);

... 符号作 Rest 用处时,能够将其解构为数组:

[...mySet] // ['a', 'b', 'c'][...myMap] // [ ['a', 1], ['b', 2], ['c', 3] ]

特地的,Map 与 Set 仅反对数组形式解构,不反对对象模式解构:

{...mySet} // {}{...myMap} // {}

但对于一个一般数组,是同时反对数组与对象模式解构的:

const arr = ['a', 'b', 'c'][...arr] // ['a', 'b', 'c']{...arr} // {0: 'a', 1: 'b', 2: 'c'}

这是因为数组变量有潜在的下标,这些下标能够转换为对象的 Key,而 Map Set 不存在下标,所以转换为对象找不到 Key,因而就不反对对象模式的解构。

更具体的起因与对象的可迭代性无关,尽管 MapSet 都反对迭代,但如果用 for key of 来测试,会发现它们的 key 是 undefined

Spread 会失落 get() 与 set()

Spread 并不代表残缺复制整个对象,它能拷贝这个对象属性定义中的瞬时值,比方:

const obj = {    a: 1,    b: get() { return 2 }}const newObj = { ...obj }

newObj.b 属性不再是 get() 办法,而是固定值 2,这在 get() 函数内返回非固定值,或心愿懒加载代码时会产生问题。

究其原因,Spread 毕竟不是在定义对象,更失当的了解应该是 “拜访对象”,所以拜访的后果就是执行 get()

Rest 会跳过不可枚举属性

const err = new Error('error'){...error} // {}

Error 领有两个不可枚举属性 messagestack,所以不会被 Rest 收集到,遇到这种场景能够应用其余形式,如间接拜访 error.message

总结

... 用在赋值地位含意为 Spread,用在参数收集地位含意为 Rest,同时因为该语法写起来很简略,因而有一些默认逻辑小心不要掉坑里,比方默认会执行对象属性的 getter,会跳过不可枚举属性等。

探讨地址是:精读《Rest vs Spread 语法》· Issue #447 · dt-fe/weekly

如果你想参加探讨,请 点击这里,每周都有新的主题,周末或周一公布。前端精读 - 帮你筛选靠谱的内容。

关注 前端精读微信公众号

<img width=200 src="https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg">

版权申明:自在转载-非商用-非衍生-放弃署名(创意共享 3.0 许可证)