有時候我們可能會想要將某一個物件的屬性複製到另一個物件,所以我們可能會寫出像下面這樣的程式碼。
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 }
// ]
// }
留言
張貼留言