prefer-object-spread

  • 2019 年 10 月 25 日
  • 筆記

eslint報錯:

  Use an object spread instead of `Object.assign` eg: `{ …foo }`.(prefer-object-spread

即:

  禁止使用以對象字面量作為第一個參數的 Object.assign,優先使用對象擴展。

 

 

示例:(注意:對象字面量)

Object.assign({}, foo)

改為:

{ ...foo }



思考一下:
Object.assign常用來淺拷貝,那擴展符賦值的對象是重新開闢的堆記憶體還是指向的擴展對象的堆記憶體?

    const a = { a: 'a' };      const b = { ...a };      console.log('b=', b);  // b= {a: "a"}      a.a = 'c';      console.log('b變了嗎', b); // b變了嗎 {a: "a"}   

  

  答案很明顯,我想淺拷貝一個a, 擴展運算符和Object.assign都能淺拷貝對象

 

  那數組會怎樣?

  

    const a = ['a', 'b'];      const b = [...a];      console.log('b=', b);  // b= ["a", "b"]      a[1] = 'c';      console.log('b變了嗎', b); // b變了嗎 ["a", "b"]

 

  很好,數組也能放心的淺拷貝;

  

  等等。。。

  

  如果是數組對象呢?

 

    const a = [{ a: 'a' }];      const b = [...a];      console.log('b=', JSON.stringify(b));  // b= [{"a":"a"}]      a[0].a = 'c';      console.log('b變了嗎', JSON.stringify(b)); // b變了嗎 [{"a":"c"}]

 

  變了,結果說明展開符只對數組裡面的對象進行了展開,對象裡面的屬性還是指向的原來的記憶體地址,所以深拷貝行不通,目前來看和Object.assign的淺拷貝作用一樣。

 

那…等等,

  

  Object.assign還有合併的作用,再來試試擴展符合併。

  

  

    const a = { a1: 'a1', a2: 'a2' };      const b = { b1: 'b1', a2: 'b2' };      const c = Object.assign({}, a, b);      const d = { ...a, ...b };      const e = { ...b, ...a };      console.log('c', c);  // c {a1: "a1", a2: "b2", b1: "b1"}      console.log('d', d);  // d {a1: "a1", a2: "b2", b1: "b1"}      console.log('e', e);  // e {b1: "b1", a2: "a2", a1: "a1"}

 

   結果一樣,Object.assign將b和a的屬性合併到空對象里,相同屬性會覆蓋合併取後面的值,擴展符直接合併兩個對象的屬性,合併關係都是後面的覆蓋前面的值

 

   那麼,合併數組呢?

 

    const a = ['a', 'b'];      const b = ['a', 'c'];      const c = Object.assign([], a, b);      const d = [...a, ...b];      console.log('c', c);  // c ["a", "c"]      console.log('d', d);  // d ["a", "b", "a", "c"]

 

   發生了什麼?

   Object.assign處理數組時,會把數組視為對象,然後按順序覆蓋前面的值,所以b中的’a’覆蓋了a中的’a’, b中的’c’覆蓋了a中的’b’,而擴展符和concat方法一樣合併數組

 

   合併數組時,Object.assign和擴展符作用不一樣了。

   

   那麼,複雜數組呢?

    const a = [{ x: 'x', y: 'y' }];      const b = [{ z: 'z', y: 'm' }];      const c = Object.assign([], a, b);      const d = [...a, ...b];      console.log('c', JSON.stringify(c)); // c [{"z":"z","y":"m"}]      console.log('d', JSON.stringify(d)); // d [{"x":"x","y":"y"},{"z":"z","y":"m"}]      b[0].z = 'n';      console.log('c', JSON.stringify(c)); // c [{"z":"n","y":"m"}]      console.log('d', JSON.stringify(d)); // d [{"x":"x","y":"y"},{"z":"n","y":"m"}]

  

  Object.assign毫無懸念的後面的覆蓋前面了(將數組看做對象時,屬性就是下標),引用類型指向的還是原來的記憶體地址

  

 

最後:

  

  雖然說Object.assign和...擴展符很多時候能混用,但對數組進行操作的時候一定要小心兩者的區別,不然合併覆蓋變成合併拼接,所以請牢記使用以對象字面量作為第一個參數的 Object.assign,優先使用對象擴展