剩余参数与展开语法
剩余参数与 arguments 有什么区别?
| 维度 | ...rest | arguments |
|---|---|---|
| 类型 | 真数组, 支持数组方法 | 类数组且可迭代, 非数组 |
| 收集范围 | 只收未具名的尾部实参 | 永远包含全部实参 |
| 箭头函数 | 可用 | 没有自己的 arguments |
function showName(firstName, lastName, ...titles) {
titles; // ["Consul", "Imperator"]
}
- 位置错误:
function g(arg1, ...rest, arg2)直接报错,...rest之后不能再有形参; - 部分收集: 只有
...rest能"前几个进变量, 其余进数组"; - 选型: 新代码用
...rest,arguments只用于旧代码;
展开语法能展开什么?
- 判定规则:
...在形参列表末尾是剩余参数, 在调用或字面量中则是展开语法, 两者同形反向; - 展开依据: 内部用迭代器收集元素, 与
for...of同一协议, 所以任何可迭代对象都行;
Math.max([3, 5, 1]); // NaN
Math.max(...[3, 5, 1]); // 5
Math.max(1, ...arr1, 2, ...arr2, 25); // 可与普通值、多个可迭代对象混用
[..."Hello"]; // ["H","e","l","l","o"], 同 Array.from(str)
- 类数组: 可迭代的类数组 (如
arguments) 能直接展开; 仅"类数组但不可迭代"的对象须用Array.from, 它两者都接受, 展开语法只接受可迭代; - 调用与
new: 展开用在参数位置, 函数调用与new F(...args)都能接收; - 普通对象:
{...obj}是另一套语义 (复制自身可枚举属性), 与迭代器无关;
展开语法如何用于拷贝与合并?
- 浅拷贝与合并:
[...arr]、{...obj}、[...a, ...b]、{...a, ...b}, 后者同名属性覆盖前者; - 对比:
{...obj}等价于Object.assign({}, obj)但更短, 优先使用; - 深浅边界: 只复制第一层, 嵌套对象仍共享引用, 见 深浅拷贝;