一:区别
浅拷贝和深拷贝的区别在于当a复制了b之后,b修改会不会影响到a,如果会影响,那么就是浅拷贝,否则是深拷贝。
二:浅拷贝
let arr = [1, 2, 3];
let arr2 = arr;
console.log(arr); // 1, 2, 3
console.log(arr2); // 1, 2, 3
arr2.push(22);
console.log(arr); // 1, 2, 3, 22
console.log(arr2); // 1, 2, 3, 22
这个例子就是浅拷贝,原因是arr和arr2都是指向同一个地址,前面的文章有专门讲过。(JavaScript的值和引用)
三:深拷贝
深拷贝有很多种实现方式,可以根据实际情况自行定义合适自己使用的最佳方案。
demo1:数组
// 深拷贝demo1
let arr = [1, 2, 3];
function deepClone(arr) {
let newarr = [];
for(let i = 0; i < arr.length; i++) {
newarr.push(arr[i])
}
return newarr;
}
let arr2 = deepClone(arr);
console.log(arr); // 1, 2, 3
console.log(arr2); // 1, 2, 3
arr2.push(333)
console.log(arr); // 1, 2, 3
console.log(arr2); // 1, 2, 3, 333
demo2:对象
// 深拷贝demo2
let obj = {a: 123, b: 456, c: {a: 123, b: 456}}
function deepClone(obj) {
let newObj = {};
for(let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
let obj2 = deepClone(obj);
console.log(obj); // {a: 123, b: 456, c: {…}}
console.log(obj2); // {a: 123, b: 456, c: {…}}
obj2.d = "666";
console.log(obj); // {a: 123, b: 456, c: {…}}
console.log(obj2); // {a: 123, b: 456, c: {…}, d: "666"}
上面两个demo看似完成了深拷贝,但实际上换一个写法却是有问题的,看demo3
// 深拷贝demo3
let obj = {a: 123, b: 456, c: {a: 123, b: 456}}
function deepClone(obj) {
let newObj = {};
for(let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
let obj2 = deepClone(obj);
console.log(obj); // {a: 123, b: 456, c: {…}}
console.log(obj2); // {a: 123, b: 456, c: {…}}
obj2.c.a = "666";
console.log(obj, obj2); // {a: 123, b: 456, c: {…}} {a: 123, b: 456, c: {…}}
打印出来可以看到,c里面的a,被影响到了,代码中只修改了obj2的,但是obj确也跟着变了。说明这个方法还不管用,只能拷贝到第一层级的。(该例子用于数组也是一样)
那么怎么样才可以更深层次的拷贝一个对象呢?来看demo4
// 深拷贝demo4
let obj = {a: 123, b: 456, c: {a: 123, b: 456}}
function deepClone(obj) {
let newObj = JSON.parse(JSON.stringify(obj));
return newObj;
}
let obj2 = deepClone(obj);
console.log(obj); // {a: 123, b: 456, c: {…}}
console.log(obj2); // {a: 123, b: 456, c: {…}}
obj2.c.a = "666";
console.log(obj, obj2); // {a: 123, b: 456, c: {…}} {a: 123, b: 456, c: {…}}
看到了吧,此时修改obj2里面的c的属性,obj是不会受到任何影响的。这个方法还更简单,代码量还少,最重要的是实现了真正意义上的深克隆。