Get to know MDN better
此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。
spread (...) 语法允许迭代数组或字符串等可迭代字符串在预期有零个或更多参数(用于函数调用)或元素(用于数组字面量)的地方进行扩展。在对象字面量中,扩展语法枚举对象的属性,并将键值对添加到正在创建的对象中。
展开语法看起来与剩余参数语法一模一样。在某种程度上,扩展语法与剩余参数语法正好相反。扩展语法是将数组“扩展”为元素,而其余语法是将多个元素收集起来,然后“浓缩”为一个元素。请参阅剩余参数和剩余属性 。
如果想将数组元素迭代为函数参数,一般使用Function.prototype.apply 的方式进行调用。
有了展开语法,可以这样写:
所有参数都可以通过展开语法来传值,也不限制多次使用展开语法。
使用 new 关键字来调用构造函数时,不能直接使用数组 + apply 的方式(apply 执行的是调用 [[Call]] , 而不是构造 [[Construct]])。当然,有了展开语法,将数组展开为构造函数的参数就很简单了:
如果不使用展开语法,想将数组元素传给构造函数,实现方式可能是这样的:
没有展开语法的时候,只能组合使用 push, splice, concat 等方法,来将已有数组元素变成新数组的一部分。有了展开语法,通过字面量方式,构造新数组会变得更简单、更优雅:
和参数列表的展开类似, ... 在构造字面量数组时,可以在任意位置多次使用。
提示: 实际上,展开语法和 Object.assign() 行为一致,执行的都是浅拷贝 (只遍历一层)。如果想对多维数组进行深拷贝,下面的示例就有些问题了。
Array.concat 函数常用于将一个数组连接到另一个数组的后面。如果不使用展开语法,代码可能是下面这样的:
使用展开语法:
Array.unshift 方法常用于在数组的开头插入新元素/数组。不使用展开语法,示例如下:
如果使用展开语法,代码如下:[请注意,这里使用展开语法创建了一个新的 arr1 数组, Array.unshift 方法则是修改了原本存在的 arr1 数组]:
Rest/Spread Properties for ECMAScript 提议 (stage 4) 对 字面量对象 增加了展开特性。其行为是,将已有对象的所有可枚举 (enumerable) 属性拷贝到新构造的对象中。
浅拷贝 (Shallow-cloning,不包含 prototype) 和对象合并,可以使用更简短的展开语法。而不必再使用 Object.assign() 方式。
提示: Object.assign() 函数会触发 setters,而展开语法则不会。
提示: 不能替换或者模拟 Object.assign() 函数:
var obj1 = { foo: 'bar', x: 42 }; var obj2 = { foo: 'baz', y: 13 }; const merge = ( ...objects ) => ( { ...objects } ); var mergedObj = merge ( obj1, obj2); // Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } } var mergedObj = merge ( {}, obj1, obj2); // Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }在这段代码中,展开操作符 (spread operator) 并没有按预期的方式执行:而是先将多个解构变为剩余参数 (rest parameter), 然后再将剩余参数展开为字面量对象。
在数组或函数参数中使用展开语法时,该语法只能用于 可迭代对象:
在函数调用时使用展开语法,请注意不能超过 JavaScript 引擎限制的最大参数个数。更多详细信息,请参考:apply()。
剩余语法 (Rest syntax) 看起来和展开语法完全相同,不同点在于,剩余参数用于解构数组和对象。从某种意义上说,剩余语法与展开语法是相反的:展开语法将数组展开为其中的各个元素,而剩余语法则是将多个元素收集起来并“凝聚”为单个元素。请参考:剩余参数。
| ECMAScript® 2027 Language Specification # prod-SpreadElement |
| ECMAScript® 2027 Language Specification # prod-ArgumentList |
| ECMAScript® 2027 Language Specification # prod-PropertyDefinition |
启用 JavaScript 以查看此浏览器兼容性表。