Object.assign() 方法用于將所有可枚舉屬性的值從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象。它將返回目標(biāo)對(duì)象碳锈。
如果目標(biāo)對(duì)象中的屬性具有相同的鍵,則屬性將被源對(duì)象中的屬性覆蓋。后面的源對(duì)象的屬性將類似地覆蓋前面的源對(duì)象的屬性滥嘴。
Object.assign 方法只會(huì)拷貝源對(duì)象自身的并且可枚舉的屬性到目標(biāo)對(duì)象。該方法使用源對(duì)象的[[Get]]和目標(biāo)對(duì)象的[[Set]]职祷,所以它會(huì)調(diào)用相關(guān) getter 和 setter氏涩。因此,它分配屬性有梆,而不僅僅是復(fù)制或定義新的屬性是尖。如果合并源包含getter,這可能使其不適合將新屬性合并到原型中泥耀。為了將屬性定義(包括其可枚舉性)復(fù)制到原型饺汹,應(yīng)使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
String類型和 Symbol 類型的屬性都會(huì)被拷貝痰催。
在出現(xiàn)錯(cuò)誤的情況下兜辞,例如,如果屬性不可寫夸溶,會(huì)引發(fā)TypeError逸吵,如果在引發(fā)錯(cuò)誤之前添加了任何屬性,則可以更改target對(duì)象缝裁。
Object.assign 不會(huì)在那些source對(duì)象值為 null或 undefined 的時(shí)候拋出錯(cuò)誤扫皱。
針對(duì)深拷貝,需要使用其他辦法,因?yàn)?Object.assign()拷貝的是屬性值韩脑。假如源對(duì)象的屬性值是一個(gè)對(duì)象的引用氢妈,那么它也只指向那個(gè)引用。也就是說段多,如果對(duì)象的屬性值為簡(jiǎn)單類型(如string首量, number),通過Object.assign({},srcObj);得到的新對(duì)象為深拷貝进苍;如果屬性值為對(duì)象或其它引用類型加缘,那對(duì)于這個(gè)對(duì)象而言其實(shí)是淺拷貝的。
深拷貝的幾種實(shí)現(xiàn)方法
JSON.stringify 和 JSON.parse
用 JSON.stringify 把對(duì)象轉(zhuǎn)換成字符串琅捏,再用 JSON.parse 把字符串轉(zhuǎn)換成新的對(duì)象生百。
可以轉(zhuǎn)成 JSON 格式的對(duì)象才能使用這種方法,如果對(duì)象中包含 function 或 RegExp 這些就不能用這種方法了柄延。
//通過js的內(nèi)置對(duì)象JSON來進(jìn)行數(shù)組對(duì)象的深拷貝
function deepClone(obj) {
let _obj = JSON.stringify(obj);
let objClone = JSON.parse(_obj);
return objClone;
}
Object.assign()拷貝
當(dāng)對(duì)象中只有一級(jí)屬性蚀浆,沒有二級(jí)屬性的時(shí)候,此方法為深拷貝搜吧,但是對(duì)象中有對(duì)象的時(shí)候市俊,此方法,在二級(jí)屬性以后就是淺拷貝滤奈。
通過jQuery的extend方法實(shí)現(xiàn)深拷貝
let $ = require('jquery');
let obj1 = {
a: 1,
b: {
f: {
g: 1
}
},
c: [1, 2, 3]
};
let obj2 = $.extend(true, {}, obj1);
lodash.cloneDeep()實(shí)現(xiàn)深拷貝
let _ = require('lodash');
let obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
let obj2 = _.cloneDeep(obj1);
使用遞歸的方式實(shí)現(xiàn)深拷貝
function _deepClone(source) {
let target;
if (typeof source === 'object') {
target = Array.isArray(source) ? [] : {}
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] !== 'object') {
target[key] = source[key]
} else {
target[key] = _deepClone(source[key])
}
}
}
} else {
target = source
}
return target
}