深拷贝一个有循环引用的对象。

在js中进行deep clone时,JSON.stringify和JSON.parse方法基本可以满足大部分要求。但是这种方案在某些特殊情况下可能无法满足需求,比如需要clone的对象中存在循环时。

循环引用大概是这样的:

1
2
3
4
5
6
7
8
9
function deepClone (obj){
return JSON.parse(JSON.stringify(obj));
}

var a = {
key: "value"
};
a.circular = a;
console.log(a);

打印出来的信息可以显示circular属性是个循环引用:

1
{ key: 'value', circular: [Circular] }

如果直接对obj调用deepClone,会抛出错误:

1
TypeError: Converting circular structure to JSON

这时可以对json序列化的过程做一次过滤,过滤掉存在循环引用的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

function deepClone(obj) {
var cache = [];
return JSON.parse(
// 用到了JSON.stringify的第二个参数
JSON.stringify(obj, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
})
);
}

主要是在cache中判断了是否存在循环引用。

参阅