有時候我們可能會想要將某一個物件的屬性複製到另一個物件,所以我們可能會寫出像下面這樣的程式碼。
    let order = {
      OrderID: 'A001',
      OrderDate: '2018-10-14'
    };
    let items = [
        { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
        { ItemName: '鉛筆', Price: 10, Quantity: 10 }
      ];
    order.Items = items;
    // Output :
    // {
    //   OrderID: 'A001',
    //   Items: [
    //     { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
    //     { ItemName: '鉛筆', Price: 10, Quantity: 10 }
    //   ],
    //   OrderDate: '2018-10-14'
    // }
如果我們有很多的屬性要做複製的話,向上面這樣的寫法實在太費時。事實上,我們可以使用Object.assign()來輕鬆地完成這件事,它用於複製一個或多個物件,將它們所有可列舉的屬性到另一個目標物件。
    let order = {
      OrderID: 'A001',
      OrderDate: '2018-10-14'
    };
    let items = [
        { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
        { ItemName: '鉛筆', Price: 10, Quantity: 10 }
      ];  
    let customer = {
       CustomerID : 'C001'
    };
    Object.assign(order,{Items:items},customer);
    // Output :
    // {
    //   OrderID: 'A001',
    //   CustomerID = 'C001',
    //   Items: [
    //     { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
    //     { ItemName: '鉛筆', Price: 10, Quantity: 10 }
    //   ],
    //   OrderDate: '2018-10-14'
    // }
或者,是當我們要將陣列或是字串內的元素複製到另一個陣列或是物件,我們也可以使用Object.assign()
    Object.assign([], [100, 200, 300]);
    // Output : [100, 200, 300]
    Object.assign({}, [100, 200, 300]);
    // Output : {100, 200, 300}
    Object.assign([], 'ABC');
    // Output : ['A','B','C']
    target = Object.assign({}, 'ABC');
    // Output : {'A','B','C'}
以上是Object.assign()的基本應用方式。
另外,在使用Object.assign()需要特別注意的事,就是Object.assign()它是淺層複製。 例如以下例子,由於Object.assign()是淺層複製,它只複製參考,所以source也會跟著被改變,故Price為100。
    let target = {};
    const source = {
      OrderID: 'A001',
      Items: [
        { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
        { ItemName: '鉛筆', Price: 10, Quantity: 10 }
      ]
    };
    Object.assign(target, source);
    for (const i of target.Items) {
      i.Price = 100;
    }
    // Source Output :
    // {
    //  OrderID: 'A001',
    //  Items: [
    //    { ItemName: '橡皮擦', Price: 100, Quantity: 10 },
    //    { ItemName: '鉛筆', Price: 100, Quantity: 10 }
    //  ]
    // }
    // Target Output :
    // {
    //  OrderID: 'A001',
    //  Items: [
    //    { ItemName: '橡皮擦', Price: 100, Quantity: 10 },
    //    { ItemName: '鉛筆', Price: 100, Quantity: 10 }
    //  ]
    // }
如果我們想要同時能夠複製物件屬性又能夠達到深層複製效果,那我們可以使用Lodash的_.merge方法來達成這件事。
如下面的例子使用_.merge後,source和target都是完全獨立的實體,所以不會互相干涉。
    let target = {};
    const source = {
      OrderID: 'A001',
      Items: [
        { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
        { ItemName: '鉛筆', Price: 10, Quantity: 10 }
      ]
    };
    _.merge(target, source);
    for (const i of target.Items) {
      i.Price = 100;
    }
    // Source Output :
    // {
    //  OrderID: 'A001',
    //  Items: [
    //    { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
    //    { ItemName: '鉛筆', Price: 10, Quantity: 10 }
    //  ]
    // }
    // Target Output :
    // {
    //  OrderID: 'A001',
    //  Items: [
    //    { ItemName: '橡皮擦', Price: 100, Quantity: 10 },
    //    { ItemName: '鉛筆', Price: 100, Quantity: 10 }
    //  ]
    // }
還有一件要注意的事,當target和source有相同屬性時,target的屬性值會被source給覆蓋掉。
如下面的例子,target的OrderID值會是'A002'。
    let target = {
      OrderID: 'A001',
      Items: [
        { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
        { ItemName: '鉛筆', Price: 10, Quantity: 10 }
      ]
    }
    const source = { 
      OrderID: 'A002',
      OrderDate: '2018-10-14' 
    };
     Object.assign(target, source);
    // Target Output :
    // {
    //  OrderID: 'A002',
    //  Items: [
    //    { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
    //    { ItemName: '鉛筆', Price: 10, Quantity: 10 }
    //  ]
    // }
假如我們想要當target和source有相同屬性時,target的值不被覆蓋掉,我們可以使用Lodash的_.defaults或_.defaultsDeep方法。
如下面的例子,target的OrderID值仍會是'A001'。
    let target = {
      OrderID: 'A001',
      Items: [
        { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
        { ItemName: '鉛筆', Price: 10, Quantity: 10 }
      ]
    }
    const source = { 
      OrderID: 'A002',
      OrderDate: '2018-10-14' 
    };
     _.defaultsDeep(target, source);
    // Target Output :
    // {
    //  OrderID: 'A001',
    //  Items: [
    //    { ItemName: '橡皮擦', Price: 15, Quantity: 10 },
    //    { ItemName: '鉛筆', Price: 10, Quantity: 10 }
    //  ]
    // }
留言
張貼留言