淺拷貝和深拷貝
- 淺拷貝: 只拷貝一層.當對象是復雜數據類型(Object、 Array)時,只拷貝引用
- 深拷貝: 多層拷貝.復雜數據類型,會重新分配內存空間.
實現淺拷貝的2種方法
- 使用
for ... in
實現
var obj = {name: 'marron',age: 18,msg: {sex: "1" }
}
var o = {};
for(let k in obj) {o[k] = obj[k]
};
console.log(o);
- 使用es6提供的方法
Object.assign
var obj = {name: 'marron',age: 18,msg: {sex: "1"}
}
var o = {};
Object.assign(o, obj);
console.log(o);
上面用實現了將對象obj
賦值給o. 但是,o中對屬性sex
的操作.是引用操作.
即改變o.msg.sex
屬性obj.msg.sex
屬性也會改變.
o.msg.sex = 2;
console.log(obj.msg.sex); // 2
實現深拷貝
很明顯上面并不是我們所需要的結果.
核心思路是,復雜數據類型賦值時先開辟內存空間.
嘗試使用遞歸實現拷貝,思路如下:
- 使用
for...in
進行賦值 - 在賦值時首先判斷當前的屬性是否為數組
a instanceof Array
,若為數組,則按照數組方式進行遞歸. - 在判斷當前的屬性是否為對象
a instanceof Object
- 剩下的認為是簡單數據類型…直接賦值即可
const deepCopy = (newobj, oldobj) => {for(let k in oldobj) {let item = oldobj[k];if(item instanceof Array) {newobj[k] = [];deepCopy(newobj[k], oldobj[k])} else if (item instanceof Object){newobj[k] = {};deepCopy(newobj[k], oldobj[k])} else {newobj[k] = item}}
}
- 測試:
let obj = {id: 1,name: 'marron',msg: {age: 18}
}
let o = deepCopy(o, obj);
console.log(o);
o.msg.age = 20;
console.log(obj);
稍微改進一下
- 上面傳遞了2個參數,且沒有考慮日期和正則的情況
- 改變遞歸出來的條件
- 使用typeof判斷是否是 數組和對象的形式
- 但是使用
typeof === ‘object’
會遺漏掉掉null的情況 - 然后使用
instanceof
來判斷正則和日期的形式
const deepClone = (obj) =>{if(obj === null) return nullif(typeof obj !== 'object') return objif(obj instanceof RegExp){return new RegExp(obj)} if(obj instanceof Date) {return new Date(obj);}let newObj = new obj.constructor;for(let k in obj){if(obj.hasOwnProperty(k)){newObj[k] = deepClone(obj[k])}}return newObj
}