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) { 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){ let result = Array.isArray(obj)?[]:{}; let _parent = parent; while(_parent){ 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],{ 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"){ if(obj instanceof RegExp){ result = new RegExp(obj.source, obj.flags) }else if(obj instanceof Date){ result = new Date(obj.getTime()); }else{ if(obj instanceof Array){ result = [] }else{ let proto = Object.getPrototypeOf(obj); result = Object.create(proto); } for(let key in obj){ 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{ return obj } return result; }
|