【JavaScript前菜】解构赋值与rest参数、展开运算符之间的微妙关系
一、数组解构
1 /** 2 * 数组解构就是将数组展开后按顺序赋给变量 3 * 其运作像极了调用方法传递参数时对数组的展开。 4 */ 5 let arr = [1,2,3]; 6 // 下面这条语句是展开运算符和数组解构的结合使用 7 let [a, ...others] = arr; 8 console.log(a); // 1 9 console.log(others); // [ 2, 3 ] 10 11 // 运作方式类似于方法接受参数 12 function A(a, ...ohters) { //该方法用rest参数(...others)接受剩余实参 13 console.log(a); // 1 14 console.log(ohters); // [ 2, 3 ] 15 } 16 A(...arr); // 将数组展开后传递给方法
二、对象解构
1 /** 2 * 在这次对象解构中,仅看这次结果 3 * 好像就是那么回事:像极了调用方法传递参数时对对象的展开。 4 */ 5 let person = { 6 name: '张三', 7 age: 18, 8 gender: '男' 9 }; 10 let {name, ...newObject} = person; 11 console.log(name); // 张三 12 console.log(newObject); // { age: 18, gender: '男' }
到这里,对解构赋值的使用语法有了更方便的理解,而且这样去理解好像并没有大毛病。
不过值得注意的是,一般的对象并不能这样展开:
1 /** 2 * 上面代码的解构的运作就像下面的一样, 3 * 只不过下面这段代码是错误的。 4 */ 5 let person = { 6 name: '张三', 7 age: 18, 8 gender: '男' 9 }; 10 function B(name, ...newObject) { 11 console.log(name); 12 console.log(newObject); 13 } 14 // 错误的大意就是person不是可迭代对象 15 B(...person); // TypeError: Found non-callable @@iterator 16 17 // 就像这样,也报同样的错 18 console.log(...person); // TypeError: Found non-callable @@iterator
这段代码的错误关系到展开运算符的语法问题,接下的交给更有权威的来🎉:
展开语法(Spread syntax), 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按key-value的方式展开。(译者注: 字面量一般指 [1, 2, 3]
或者 {name: "mdn"}
这种简洁的构造方式)
...
在数组或函数参数中使用展开语法时, 该语法只能用于 可迭代对象
...
剩余语法(Rest syntax) 看起来和展开语法完全相同,不同点在于, 剩余参数用于解构数组和对象。从某种意义上说,剩余语法与展开语法是相反的:展开语法将数组展开为其中的各个元素,而剩余语法则是将多个元素收集起来并“凝聚”为单个元素。 请参考: 剩余参数。(注:这里说的剩余参数,也就是本文标题的rest参数)
人人须日日改过,一旦无过可改,即一日无步可过矣。若发现不妥的点请务必指出,非常感谢。