翻译正在进行中。

扩展语法允许一个表达式在期望多个参数(用于函数调用)或多个元素(用于数组字面量)或多个变量(用于解构赋值)的位置扩展。

语法

函数调用:

myFunction(...iterableObj);

数组字面量或字符串:

[...iterableObj, '4', 'five', 6];

对象字面量(ECMAScript 2018中的新增内容):

let objClone = { ...obj };

示例

在函数调用中传播

取代 apply

在想要将数组的元素用作函数参数的情况下,通常使用Function.prototype.apply

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);

使用扩展语法,上面可以写成:

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);

参数列表中的任何参数都可以使用扩展语法,并且可以多次使用。

function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

在 new 中应用

当用new调用构造函数,它不可能直接使用数组和  apply (apply做了[[Call]],而不是一个[[Construct]])。然而,借助新的扩展语法可以轻松使用:

var dateFields = [1970,0,1]; // 1970年1月1日
var d = new Date(... dateFields);

要使用新的参数数组而不使用扩展语法,则必须通过部分应用程序间接完成它

function applyAndNew(constructor, args) {
   function partial () {
      return constructor.apply(this, args);
   };
   if (typeof constructor.prototype === "object") {
      partial.prototype = Object.create(constructor.prototype);
   }
   return partial;
}


function myConstructor () {
   console.log("arguments.length: " + arguments.length);
   console.log(arguments);
   this.prop1="val1";
   this.prop2="val2";
};

var myArguments = ["hi", "how", "are", "you", "mr", null];
var myConstructorWithArguments = applyAndNew(myConstructor, myArguments);

console.log(new myConstructorWithArguments);
// (internal log of myConstructor):           arguments.length: 6
// (internal log of myConstructor):           ["hi", "how", "are", "you", "mr", null]
// (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}

展开数组字面量

更强大的数组字面量

无扩散的语法,使用现有阵列作为它的一个部分创建一个新的数组,数组文本语法不再足够和命令性代码必须使用的组合来代替pushspliceconcat等。随着扩展语法此变得更加简洁:

var parts = ['shoulders','knees']; 
var lyrics = ['head',... parts,'and','toes']; 
// ["head", "shoulders", "knees", "and", "toes"]

Just like spread for argument lists, ... can be used anywhere in the array literal and it can be used multiple times.

Copy an array

var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
arr2.push(4); 

// arr2 becomes [1, 2, 3, 4]
// arr remains unaffected

Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with Object.assign() and spread syntax).

var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Now array a is affected as well: [[], [2], [3]]

A better way to concatenate arrays

Array.concat is often used to concatenate an array to the end of an existing array. Without spread syntax this is done as:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
arr1 = arr1.concat(arr2);

With spread syntax this becomes:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];

Array.unshift is often used to insert an array of values at the start of an existing array.  Without spread syntax this is done as:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Prepend all items from arr2 onto arr1
Array.prototype.unshift.apply(arr1, arr2) // arr1 is now [3, 4, 5, 0, 1, 2]

With spread syntax this becomes [Note, however, that this creates a new arr1 array. Unlike Array.unshift, it does not modify the original arr1 array in-place]:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]

展开对象字面量

The Rest/Spread Properties for ECMAScript proposal (stage 4) adds spread properties to object literals. It copies own enumerable properties from a provided object onto a new object.

Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than Object.assign().

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

请注意,Object.assign()会触发setters,而展开语法不会。

只能用于可迭代对象

扩展语法(除扩展属性外)只能应用于可迭代对象:

var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable

展开多个值

当使用扩展语法进行函数调用时,请注意超过JavaScript引擎参数长度限制的可能性。有关更多详细信息,请参阅apply()

剩余语法(参数)

剩余语法看起来与扩展语法完全相同,但用于解构数组和对象。从某种意义上说,剩余语法与展开语法相反:展开语法将数组展开为元素,而剩余语法收集多个元素并将它们“凝聚”为一个元素。 请参阅剩余参数

规范

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262) Standard Defined in several sections of the specification: Array Initializer, Argument Lists
ECMAScript Latest Draft (ECMA-262) Draft No changes.
ECMAScript Latest Draft (ECMA-262) Draft Defined in Object Initializer

浏览器兼容

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Spread in array literals461216 No378
Spread in function calls461227 No378
Spread in destructuring49 No34 No37 ?
Spread in object literals60 No55 No ? No
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Spread in array literals464612163785.0
Spread in function calls464612273785.0
Spread in destructuring4949 No3437 ?5.0
Spread in object literals6060 No55 ? No No

相关链接

文档标签和贡献者

 此页面的贡献者: fanjieqi, kczjczhYue, zhangchen, maoguojun
 最后编辑者: fanjieqi,