JSON.parse(JSON.stringify(obj))

可实现多维对象的深拷贝,但会忽略undefined、任意的函数、symbol值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var obj1 = {
x: 1,
y: {
m: 1
},
a:undefined,
b:function(a,b){
return a+b
},
c:Symbol("foo")
};
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)}
console.log(obj2) //{x: 1, y: {m: 1}}
obj2.y.m = 2; //修改obj2.y.m
console.log(obj1) //{x: 1, y: {m: 1}, a: undefined, b: ƒ, c: Symbol(foo)}
console.log(obj2) //{x: 2, y: {m: 2}}

注:进行JSON.stringify()序列化的过程中,undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。

深拷贝函数简单写法(递归实现)(乞丐版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function deepClone(obj) {
//判断返回对象或者数组,因为typeof不能区别数组与对象
var result = Array.isArray(obj) ? [] : {}
//判断是否是对象
if (obj && typeof obj === 'object') {
//便利每个键名
for (var key in obj) {
//筛选出对象自带属性
if (obj.hasOwnProperty(key)) {
//如果某个属性已然为对象
if (obj[key] && typeof obj[key] === 'object') {
//则递归此函数
result[key] = deepClone(obj[key])
}
else {
//否则直接赋值
result[key] = obj[key]
}
}
}
}
return result //返回结果
}

深拷贝函数改进(防止循环递归)(够用版)

解决因循环递归而暴栈的问题,只需要判断一个对象的字段是否引用了这个对象或这个对象的任意父级即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function deepClone(obj, parent = null){ // 改进(1)
let result = Array.isArray(obj)?[]:{};
let _parent = parent; // 改进(2)
while(_parent){ // 改进(3)
if(_parent.originalParent === obj){
return _parent.currentParent;
}
_parent = _parent.parent;
}
if(obj && typeof obj === "object"){
for(let key in obj){
if(obj.hasOwnProperty(key)){
if(obj[key] && typeof obj[key] === "object"){
result[key] = deepClone(obj[key],{ // 改进(4)
originalParent: obj,
currentParent: result,
parent: parent
});
}else{
result[key] = obj[key];
}
}
}
}
return result;
}

// 调试用
var obj1 = {
x: 1,
y: 2
};
obj1.z = obj1;
var obj2 = deepClone(obj1);
console.log(obj1); //太长了去浏览器试一下吧~
console.log(obj2); //太长了去浏览器试一下吧~

深拷贝函数最终版(支持基本数据类型、原型链、RegExp、Date类型)(至尊版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function deepClone(obj, parent = null){ 
let result; // 最后的返回结果
let _parent = parent; // 防止循环引用
while(_parent){
if(_parent.originalParent === obj){
return _parent.currentParent;
}
_parent = _parent.parent;
}

if(obj && typeof obj === "object"){ // 返回引用数据类型(null已被判断条件排除))
if(obj instanceof RegExp){ // RegExp类型
result = new RegExp(obj.source, obj.flags)
}else if(obj instanceof Date){ // Date类型
result = new Date(obj.getTime());
}else{
if(obj instanceof Array){ // Array类型
result = []
}else{ // Object类型,继承原型链
let proto = Object.getPrototypeOf(obj);
result = Object.create(proto);
}
for(let key in obj){ // Array类型 与 Object类型 的深拷贝
if(obj.hasOwnProperty(key)){
if(obj[key] && typeof obj[key] === "object"){
result[key] = deepClone(obj[key],{
originalParent: obj,
currentParent: result,
parent: parent
});
}else{
result[key] = obj[key];
}
}
}
}
}else{ // 返回基本数据类型与Function类型,因为Function不需要深拷贝
return obj
}
return result;
}