對於 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); //1 //2 //3
從上面的代碼可以看出 ... 擴展運算符可以簡化我們的代碼。
我們再來看下面的代碼:
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); // 1 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);