1. 程式人生 > >es6之擴展運算符 三個點(...)

es6之擴展運算符 三個點(...)

結構 所有 數據類型 edi nts ket ... 分別是 是個

對象的擴展運算符

理解對象的擴展運算符其實很簡單,只要記住一句話就可以:

對象中的擴展運算符(...)用於取出參數對象中的所有可遍歷屬性,拷貝到當前對象之中

let bar = { a: 1, b: 2 };
let baz = { ...bar }; // { a: 1, b: 2 }

上述方法實際上等價於:

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

Object.assign方法用於對象的合並,將源對象(source)的所有可枚舉屬性,復制到目標對象(target)

Object.assign方法的第一個參數是目標對象,後面的參數都是源對象。(如果目標對象與源對象有同名屬性,或多個源對象有同名屬性,則後面的屬性會覆蓋前面的屬性)。

同樣,如果用戶自定義的屬性,放在擴展運算符後面,則擴展運算符內部的同名屬性會被覆蓋掉。

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

利用上述特性就可以很方便的修改對象的部分屬性。在redux中的reducer函數規定必須是一個純函數(如果不是很清楚什麽是純函數的可以參考這裏),reducer中的state對象要求不能直接修改,可以通過擴展運算符把修改路徑的對象都復制一遍,然後產生一個新的對象返回。

這裏有點需要註意的是擴展運算符對對象實例的拷貝屬於一種淺拷貝。肯定有人要問什麽是淺拷貝?我們知道javascript中有兩種數據類型,分別是基礎數據類型引用數據類型基礎數據類型是按值訪問的,常見的基礎數據類型NumberStringBooleanNullUndefined,這類變量的拷貝的時候會完整的復制一份;引用數據類型比如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,如果改成這樣:

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是一個引用數據類型,拷貝的時候拷貝的是對象的引用。

數組的擴展運算符

擴展運算符同樣可以運用在對數組的操作中。

  • 可以將數組轉換為參數序列
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" ]
  • 任何 Iterator 接口的對象(參閱 Iterator 一章),都可以用擴展運算符轉為真正的數組

這點說的比較官方,大家具體可以參考阮一峰老師的ECMAScript 6入門教程。

比較常見的應用是可以將某些數據結構轉為數組,比如:

// arguments對象
function foo() {
  const args = [...arguments];
}
參考路徑https://blog.csdn.net/astonishqft/article/details/82899965

es6之擴展運算符 三個點(...)