Open Genzhen opened 3 years ago
function deepCloneObj(obj) {
if(obj == null) return obj;
const o = Object.assign({}, obj);
Object.keys(o).forEach(k => {
const v = o[k];
if(Object.prototype.toString.call(v) == '[object Object]') {
// 如果是循环引用,会造成递归爆栈,使用set集合装对象,如果有相同的对象直接返回
const set = Object.prototype.toString.call(deepCloneObj[Symbol.for('cache')]) == "[object Set]"
? deepCloneObj[Symbol.for('cache')]
: deepCloneObj[Symbol.for('cache')] = new Set();
if(set.has(v)) {
o[k] = v;
}else{
set.add(v);
o[k] = deepCloneObj(v);
}
}else if(Object.prototype.toString.call(v) == '[object Array]') {
o[k] = deepCloneArr(v);
function deepCloneArr(arr) {
const tmp = [];
for(let i = 0; i < arr.length; i++) {
const item = arr[i];
if(Object.prototype.toString.call(item) == '[object Object]') {
tmp.push(deepCloneObj(item));
}else if(Object.prototype.toString.call(item) == '[object Array]') {
tmp.push(deepCloneArr(item));
}else {
tmp.push(item)
}
}
return tmp;
}
}
})
return o;
}
var obj = {
a: 1,
b: 2,
c: [1, 2, 3],
d: { aa: 1, bb: 2 },
};
obj.e = obj;
deepCloneObj(obj);
var test1 = { a: { a: 'a' } };
test1.z = test1;
var test2 = clone(test1);
test2.z.z.a.a = 'z';
console.log(test1.a.a); // 会输出 'z',但不是应该输出'a'吗
扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。
循环引用问题
看个例子
从例子可以看到,当存在循环引用的时候,deepCopy 会报错,栈溢出。
循环应用问题解决
大家都知道,对象的 key 是不能是对象的。
参考解决方式一:使用 weekmap:
解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系
这个存储空间,需要可以存储
key-value
形式的数据,且key
可以是一个引用类型,我们可以选择
WeakMap
这种数据结构:WeakMap
中有无克隆过的对象key
,克隆对象作为value
进行存储参考解决方式二:
可以用 Set,发现相同的对象直接赋值,也可用 Map