想要克隆一个对象或数组,如果只是普通的赋值,那么只是复制了浅层,深层的引用值其实指向的是同一块内存。
JSON克隆法
第一次看到这种克隆方法,把我惊呆了,还能这样克隆?
function JSONDeepClone(origin) {
return JSON.parse(JSON.stringify(origin));
}
但这个方法也有缺点,当对象中包含【Function函数、Date日期对象、RegExp正则对象】时,克隆出的对象无法复制这些属性。
递归克隆
再很久以前学基础js的时候,就自己试着写了一下递归深度克隆,能深度克隆数组和对象。
function deepClone(origin) {
let target;
// 判断传入的origin的类型
if (getType(origin) == '[object Object]') {
target = {};
}else if (getType(origin) == '[object Array]') {
target = [];
}else{
return origin;
}
// 遍历值,for-in可以遍历数组、对象
for(const key in origin){
// 如果值是数组或对象,递归继续克隆
if (getType(origin[key]) == '[object Object]' || getType(origin[key]) == '[object Array]') {
target[key] = deepClone(origin[key]);
}
//如果不是,直接赋值
else{
target[key] = origin[key];
}
}
return target;
}
// 判断类型
function getType(sth) {
return Object.prototype.toString.call(sth);
}
当然,这里还有缺陷。克隆出来的对象,函数、日期对象、正则对象等其实也是同一个引用。
对于解决日期对象,可以使用这种方法(同时在遍历值的时候,是否继续递归克隆的条件判断要多加上Date)
if (getType(origin) == '[object Date]') {
return new Date(origin.getTime());
}
对于正则也是同样的思路,如果是[object RegExp]
,就new RegExp
,用正则的一些属性获取被克隆的正则对象的信息