1.通过JSON.stringify()和JSON.parse()进行深拷贝
let obj1 = {"a": {"b": [1,2,3, {"c": 4}]}, "d": [5,6,{"e": [7,8,9]}]};
let obj2 = JSON.parse(JSON.string(obj1));
let arr1 = [1,2,{"a": 3, "b":[4,5,{"d": 6}]},[7,[8,[9,{"e": {"f": 10}}]]]];
let arr2 = JSON.parse(JSON.string(obj1));
JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象;
弊端: 时间,正则,函数,Error,NaN都无法转换,只能转换数组,对象,number,string
2.深拷贝函数
let data = ["a", {"a1": function(){}}, [1,2,3, [4,5,6]], new RegExp('\\w+')];
function judjeType(data) {
return Object.prototype.toString.call(data);
}
function deepClone(data) {
let newData = null;
let type = judjeType(data);
if (type == "[object Object]") {
newData = {};
for (let key in data) {
newData[key] = deepClone(data[key]);
}
} else if (type == "[object Array]") {
newData = [];
for (var i = 0; i < data.length; i++) {
newData.push(deepClone(data[i]))
}
} else {
return data;
}
return newData;
}
deepClone(data);
代码在执行时,每次遇到新的数组或者对象时,都会生成新的子集(从代码维度也是),不会因为有新的newData造成之前的数据找不到,这里很容易理解偏差,举个例子,就行俄罗斯的套娃游戏一样,最外层就是第一个for循环(可以是数组也可以是对象),当发现新的数组或者对象时,会生成一个新的子集,就相当于最外层的娃娃里面有生成了一个比现在小的娃娃,如果还有对象或者数组就继续生成,生成结束后会得到一个结果返回上一级,知道最外层循环结束得到最后的结果。
3.es6里面的{...}和[...]
{...}和[...]都属于浅拷贝,只能拷贝对象和数组里的第一层,第二层包括第二层以后的都无法拷贝。
let obj1 = {"a": {"b": [1,2,3, {"c": 4}]}, "d": [5,6,{"e": [7,8,9]}], "f": 10};
let obj2 = {...obj1};
obj1.a.b[0] = 0;
obj1.f = 11;
console.log(obj1, obj2)
//obj1 = {"a": {"b": [0,2,3, {"c": 4}]}, "d": [5,6,{"e": [7,8,9]}], "f": 11};
//obj2 = {"a": {"b": [0,2,3, {"c": 4}]}, "d": [5,6,{"e": [7,8,9]}], "f": 10};
let arr1 = [1,2,{"a": 3, "b":[4,5,{"d": 6}]},[7,[8,[9,{"e": {"f": 10}}]]]];
let arr2 = [...arr1];
arr1[0] = 0;
arr1[2].b[0] = 44;
console.log(arr1, arr2)
//arr1 = [0,2,{"a": 3, "b":[44,5,{"d": 6}]},[7,[8,[9,{"e": {"f": 10}}]]]];
//arr2 = [1,2,{"a": 3, "b":[44,5,{"d": 6}]},[7,[8,[9,{"e": {"f": 10}}]]]];
4.Object.assign()
let source = { a: 1 };
let target = Object.assign({}, source);
console.log(target) // { a: 1 }
source.a = 2;
console.log(source) // { a: 2 }
console.log(target) // { a: 1 }
let source = { a: { b : 1 }, c: 1 };
let target = Object.assign({}, source);
console.log(target) // { a: { b: 1 }, c: 1 }
source.a.b = 2;
source.c = 3
console.log(source) // { a: { b: 2 }, c: 3 }
console.log(target) // { a: { b: 2 }, c: 1 }
只能拷贝对象中的第一个层级。