理解對象的擴展運算符其實很簡單,只要記住一句話就能夠:javascript
對象中的擴展運算符(...)用於取出參數對象中的全部可遍歷屬性,拷貝到當前對象之中
let bar = { a: 1, b: 2 }; let baz = { ...bar }; // { a: 1, b: 2 }
上述方法實際上等價於:java
let bar = { a: 1, b: 2 }; let baz = Object.assign({}, bar); // { a: 1, b: 2 }
Object.assign
方法用於對象的合併,將源對象(source)
的全部可枚舉屬性,複製到目標對象(target)
。react
Object.assign
方法的第一個參數是目標對象,後面的參數都是源對象。(若是目標對象與源對象有同名屬性,或多個源對象有同名屬性,則後面的屬性會覆蓋前面的屬性)。es6
一樣,若是用戶自定義的屬性,放在擴展運算符後面,則擴展運算符內部的同名屬性會被覆蓋掉。redux
let bar = {a: 1, b: 2}; let baz = {...bar, ...{a:2, b: 4}}; // {a: 2, b: 4}
利用上述特性就能夠很方便的修改對象的部分屬性。在redux
中的reducer
函數規定必須是一個純函數(若是不是很清楚什麼是純函數的能夠參考這裏),reducer
中的state
對象要求不能直接修改,能夠經過擴展運算符把修改路徑的對象都複製一遍,而後產生一個新的對象返回。數組
這裏有點須要注意的是擴展運算符對對象實例的拷貝屬於一種淺拷貝。確定有人要問什麼是淺拷貝?咱們知道javascript
中有兩種數據類型,分別是基礎數據類型和引用數據類型。基礎數據類型是按值訪問的,常見的基礎數據類型有Number
、String
、Boolean
、Null
、Undefined
,這類變量的拷貝的時候會完整的複製一份;引用數據類型好比Array
,在拷貝的時候拷貝的是對象的引用,當原對象發生變化的時候,拷貝對象也跟着變化,好比:數據結構
let obj1 = { a: 1, b: 2}; let obj2 = { ...obj1, b: '2-edited'}; console.log(obj1); // {a: 1, b: 2} console.log(obj2); // {a: 1, b: "2-edited"}
上面這個例子擴展運算符拷貝的對象是基礎數據類型,所以對obj2
的修改並不會影響obj1
,若是改爲這樣:less
let obj1 = { a: 1, b: 2, c: {nickName: 'd'}}; let obj2 = { ...obj1}; obj2.c.nickName = 'd-edited'; console.log(obj1); // {a: 1, b: 2, c: {nickName: 'd-edited'}} console.log(obj2); // {a: 1, b: 2, c: {nickName: 'd-edited'}}
這裏能夠看到,對obj2
的修改影響到了被拷貝對象obj1
,緣由上面已經說了,由於obj1
中的對象c
是一個引用數據類型,拷貝的時候拷貝的是對象的引用。函數
擴展運算符一樣能夠運用在對數組的操做中。ui
function add(x, y) { return x + y; } const numbers = [4, 38]; add(...numbers) // 42
若是直接經過下列的方式進行數組複製是不可取的:
const arr1 = [1, 2]; const arr2 = arr1; arr2[0] = 2; arr1 // [2, 2]
緣由上面已經介紹過,用擴展運算符就很方便:
const arr1 = [1, 2]; const arr2 = [...arr1];
仍是記住那句話:擴展運算符(...)用於取出參數對象中的全部可遍歷屬性,拷貝到當前對象之中,這裏參數對象是個數組,數組裏面的全部對象都是基礎數據類型,將全部基礎數據類型從新拷貝到新的數組中。
const [first, ...rest] = [1, 2, 3, 4, 5]; first // 1 rest // [2, 3, 4, 5]
須要注意的一點是:
若是將擴展運算符用於數組賦值,只能放在參數的最後一位,不然會報錯。
const [...rest, last] = [1, 2, 3, 4, 5]; // 報錯 const [first, ...rest, last] = [1, 2, 3, 4, 5]; // 報錯
[...'hello'] // [ "h", "e", "l", "l", "o" ]
這點說的比較官方,你們具體能夠參考阮一峯老師的ECMAScript 6入門教程。
比較常見的應用是能夠將某些數據結構轉爲數組,好比:
// arguments對象 function foo() { const args = [...arguments]; }
用於替換es5
中的Array.prototype.slice.call(arguments)
寫法。
擴展運算符的用法就說到這裏,介紹的不全但都是些最多見的用法。
下面的是個人公衆號二維碼圖片,歡迎關注。