首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Spread operator

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

语法

用于函数调用:

代码语言:javascript
复制
myFunction(...iterableObj);

用于数组字面量:

代码语言:javascript
复制
[...iterableObj, 4, 5, 6];

用于对象字面量 (new in ECMAScript; stage 3 draft):

代码语言:javascript
复制
let objClone = { ...obj };

范例

在函数调用中

更好的 apply 方法

在需要使用数组作为函数的参数的情况下,通常使用 Function.prototype.apply 方法:

代码语言:javascript
复制
function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);

如果使用了ES6的展开运算符,你可以这么写:

代码语言:javascript
复制
function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);

就像扩展参数列表一样,...可以在数组字面量中的任何地方使用,可以多次使用。

代码语言:javascript
复制
function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

配合new运算符

例子:在ES5中,我们无法同时使用 new 运算符和 apply 方法(apply方法调用[[Call]]而不是[[Construct]])。在ES6中,我们可以使用扩展运算符,和普通的函数调用一样。

代码语言:javascript
复制
var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);

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

代码语言:javascript
复制
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"}

Spread in array literals

一个更好的连接数组的方法

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

代码语言:javascript
复制
var parts = ['shoulders', 'knees']; 
var lyrics = ['head', ...parts, 'and', 'toes']; 
// ["head", "shoulders", "knees", "and", "toes"]

就像传递参数列表一样,...可以在数组文字中的任何位置使用,并且可以多次使用。

复制一个数组

代码语言:javascript
复制
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
arr2.push(4); 

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

Note:复制数组时候, 拓展语句只会进行浅复制, 因此如下所示, 它并不适合复制多维数组 (与Object.assign()相同)。

代码语言:javascript
复制
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通常用于将数组连接到现有数组的末尾。如果没有扩展语法,这是完成的:

代码语言:javascript
复制
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
arr1 = arr1.concat(arr2);

有spread语法:

代码语言:javascript
复制
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];

Array.unshift通常用于在现有数组的开始插入一个数组值。如果没有扩展语法,这是完成的:

代码语言:javascript
复制
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:

代码语言:javascript
复制
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]

Spread in object literals

The Rest/Spread Properties for ECMAScript proposal (stage 3) 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().

代码语言:javascript
复制
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 }

Note that Object.assign() triggers setters whereas spread syntax doesn't.

Only for iterables

Spread syntax (other than in the case of spread properties) can be applied only to iterable objects:

代码语言:javascript
复制
var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable

Spread with many values

When using spread syntax for function calls, be aware of the possibility of exceeding the JavaScript engine's argument length limit. See apply() for more details.

剩余操作符

还有一种操作符叫做剩余操作符(the rest operator),它的样子看起来和展开操作符一样,但是它是用于解构数组和对象。在某种程度上,剩余元素和展开元素相反,展开元素会“展开”数组变成多个元素,剩余元素会收集多个元素和“压缩”成一个单一的元素。

规范

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)

Living Standard

No changes.

Rest/Spread Properties for ECMAScript

Draft

Stage 3 draft.

浏览器兼容性

Feature

Chrome

Edge

Firefox (Gecko)

Internet Explorer

Opera

Safari (WebKit)

Spread in array literals

46

20 (12.10240)

16 (16)

No support

37

7.1

Spread in function calls

46

20 (12.10240)

27 (27)

No support

37

7.1

Spread in destructuring

49

No support

34 (34)

No support

37

?

Spread in object literals

60

No support

55 (55)

No support

No support

No support

Feature

Android Webview

Edge

Firefox Mobile (Gecko)

IE Mobile

Opera Mobile

Safari Mobile

Chrome for Android

Spread in array literals

46

20 (12.10240)

16.0 (16)

No support

No support

8

46

Spread in function calls

46

20 (12.10240)

27.0 (27)

No support

No support

8

46

Spread in destructuring

No support

No support

34.0 (34)

?

?

?

No support

Spread in object literals

No support

No support

55.0 (55)

No support

No support

No support

No support

扫码关注腾讯云开发者

领取腾讯云代金券