const deepClone =(initalObj) =>
{
if (typeof initalObj !== 'object') {//如果是基本類型直接返回值
return initalObj
}
const obj = Array.isArray(initalObj)?[]:{};//可能是對象或者數組
for (const key in initalObj) {
if (typeof initalObj[key] === 'object') {//對於對象元素,deepclone
//遞歸返回新的對象
obj[key] = deepClone(initalObj[key]);
} else if (typeof initalObj[key] === 'function') {//對於函數,用bind拷貝
//返回新函數
obj[key] = initalObj[key].bind(obj);
} else {
//基本類型直接返回
obj[key] = initalObj[key];
}
}
return obj;
}
改進:
通過遞歸可以簡單實現對象的深度克隆,但是這種方法不管是ES6還是ES5實現,都有同樣的缺陷,就是隻能實現特定的object的深度複製(比如數組和函數),不能實現包裝對象Number,String , Boolean,以及Date對象,RegExp對象的複製。
下面是完美版的深拷貝
參考自:https://blog.csdn.net/liwusen/article/details/78759373
function istype(obj,type){//判斷包裝類型的原型
return Object.prototype.toString.call(obj).indexOf(type)!=-1
}
const deepClone =(initalObj) =>
{
if (typeof initalObj !== 'object') {//如果是基本類型直接返回值
return initalObj
}
if(istype(initalObj,'String')||istype(initalObj,'Number')||istype(initalObj,'Boolean'))
return initalObj.valueOf();
if(istype(initalObj,'Date'))
return new Date(initalObj.valueOf());
if(istype(initalObj,'RegExp')){
let pattern = initalObj.valueOf();
let flags = '';
flags += pattern.global ? 'g' : '';
flags += pattern.ignoreCase ? 'i' : '';
flags += pattern.multiline ? 'm' : '';
return new RegExp(pattern, flags);
}
const obj = Array.isArray(initalObj)?[]:{};//可能是對象或者數組
for (const key in initalObj) {
if (typeof initalObj[key] === 'object') {//對於對象元素,deepclone
//遞歸返回新的對象
obj[key] = deepClone(initalObj[key]);
} else if (typeof initalObj[key] === 'function') {//對於函數,用bind拷貝
//返回新函數
obj[key] = initalObj[key].bind(obj);
} else {
//基本類型直接返回
obj[key] = initalObj[key];
}
}
return obj;
}
測試
const obj = {
a: 1,
b: {b1:[],b2:[]},
c: { d: {}, g: () => {} },
e: () => {},
f: function() {}
}
const newObj = deepClone(obj);
console.log(newObj.a === obj.a);
console.log(newObj.b === obj.b);
console.log(newObj.c === obj.c);
console.log(newObj.c.d === obj.c.d);
console.log(newObj.c.g === obj.c.g);
console.log(newObj.e === obj.e);
console.log(newObj.f === obj.f);
const o2=deepClone([0,obj,[1]])
console.log(o2);
var str=new String("hello");
console.log(Object.prototype.toString.call(str))
console.log(deepClone(str));
console.log(Object.prototype.toString.call(new Number()))
console.log(deepClone(new Number(100)));
console.log(Object.prototype.toString.call(new Date()))
console.log(deepClone(new Date()));
console.log(Object.prototype.toString.call(new RegExp('/111/')))
console.log(deepClone(new RegExp('/111/')));