對於 ES6 新特性中的 ... 可以簡單的理解為下面一句話就可以了:

物件中的擴充套件運算子(...)用於取出引數物件中的所有可遍歷屬性,拷貝到當前物件之中。

作用類似於 Object.assign() 方法,我們先來看一下 Object.assign() 方法:

Object.assign() 方法用於將所有可列舉屬性的值從一個或多個源物件複製到目標物件。它將返回目標物件。如下:

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source); console.log(target); // { a: 1, b: 4, c: 5 }
console.log(returnedTarget); // { a: 1, b: 4, c: 5 }

語法

Object.assign(target, ...sources)

引數: target(目標物件), sources(源物件)

返回值: 目標物件。

Object.assign() 方法中如果有相同的物件屬性前面的會被後面的替換掉。

接下來我們看一個最簡單的例子:

let bar = { a: 1, b: 2 };
let baz = { ...bar };
console.log(baz); // { a: 1, b: 2 }

從上面可以看出 ... 擴充套件運算子就是將一個引數物件整體遍歷再拷貝到當前物件中,再看下面的例子:

let bar = {a: 1, b: 2};
let baz = {...bar, ...{a: 2, b: 4}};
console.log(bar); // { a: 1, b: 2 }
console.log(baz); // { a: 2, b: 4 }

... 擴充套件運算子如果有想用的物件屬性,那麼後者會將前者覆蓋掉。同時我們也可以看出這是一個淺拷貝,並不會將源物件更改掉。

但是如果是如下程式碼:

let obj1 = { a: 1, b: {name: 'aaa'}};
let obj2 = { ...obj1};
obj2.a = 2;
obj2.b.name = 'bbb';
console.log(obj1); // {a: 1, b: {name: 'bbb'}}
console.log(obj2); // {a: 2, b: {name: 'bbb'}}

從上面我們班可以看出,當 obj2 的 a 屬性改變時,obj1 內的 a 屬性不會跟著改變,但是當 obj2 的 b 屬性改變時,obj1 內的 b 屬性會跟著改變,這是由於 obj1 的 b 屬性是引用資料型別,拷貝的時候拷貝的是物件的引用,但是基礎資料型別會完整的複製出一份來。

擴充套件運算子也可以對陣列進行運算,因為陣列也屬於物件的一種,如下:

var foo = function(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
} var arr = [1, 2, 3]; //傳統寫法
foo(arr[0], arr[1], arr[2]); //使用擴充套件運算子
foo(...arr);
//
//
//

從上面的程式碼可以看出 ... 擴充套件運算子可以簡化我們的程式碼。

我們再來看下面的程式碼:

let arr1 = [1, 2];
let arr2 = arr1;
arr2[0] = 2;
console.log(arr1); // [2, 2]

上面我們已經解釋過了,arr2 其實是 arr1 的引用,如果改變 arr2 那麼 arr1 也會跟著改變,但是我們不想讓 arr1 跟著改變怎麼辦呢?用 ... 擴充套件運算子就不會了:

let arr1 = [1, 2];
let arr2 = [...arr1];
arr2[0] = 2;
console.log(arr1); // [1, 2]

上面我們已經說過了,基礎資料型別會重新完整的拷貝除一份來,這就完美的解決了上面的問題。

擴充套件運算子還可以將字串轉為陣列,如下:

let str = "hello";
let arr = [...str];
console.log(arr); // [ 'h', 'e', 'l', 'l', 'o' ]

注意:

如果將擴充套件運算子用於陣列賦值,只能放在引數的最後一位,否則會報錯。

如下:

let [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); //
console.log(rest); // [2, 3, 4, 5]
let [...first, last] = [1, 2, 3, 4, 5];
console.log(first); // 報錯 Rest element must be last element
console.log(last);
let [first, ...rest, last] = [1, 2, 3, 4, 5];
console.log(first); // 報錯 Rest element must be last element
console.log(rest);
console.log(last);