浅拷贝
我们看一下这个例子:
let a = {title:'深复制'};
let b = a;
a.title = '浅复制';
console.log(a)
console.log(b)
咦,为啥嘞!!!!!!为啥两个都是输出"浅复制"。。。。
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
const object1 = {
a: 1,
b: 2,
c: 3
};
const object2 = Object.assign({c: 4, d: 5}, object1);
console.log(object1);
console.log(object2);
这是浅拷贝,返回的不是一个新对象,而是把一个或多个源对象添加到目标对象
其实,a,b是共用同一个地址,所以虽然看起来是两个对象,其实就是一个对象,a===b,这就是深复制,复制的不仅仅是数据,而且连地址一起复制过来了,相当于Windows的快捷方式,表面上看起来一个在C盘,一个在D盘,其实都是一个文件。
深拷贝
1. 方法一
let object1 = {
a: 1,
b: 2,
c: 3
};
let object2 = {...object1};
object1.a = 11;
console.log(object1);
console.log(object2);
我们再来看打印结果
这样我们虽然复制了object1
的所有数据,但是object1和object2是不同的对象,更改任意一个的数据,不会影响到第二个
2. 方法二 – 手动复制
把一个对象的属性复制给另一个对象的属性
var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- 沒被改到
console.log(obj2);
// { a: 10, b: 100, c: 30 }
但这样很麻烦,要一个一个自己复制;而且这样的本质也不能算是 Deep Copy,因为对象里面也可能回事对象,如像下面这个状况:
3. 方法三
最简单的深拷贝(JSON.stringify() 和JSON.parse())
先把对象使用JSON.stringify()转为字符串,再赋值给另外一个变量,然后使用JSON.parse()转回来即可。
let object1 = {
a: 1,
b: 2,
c: 3
};
let object2 =JSON.parse( JSON.stringify(object1));
object2.a=11;
console.log(object1,object2);
这种方式也是深拷贝。但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
4. 方法四(数组)
slice
var arr = ['a', 'b', 'c'];
var arrCopy = arr.slice(0);
arrCopy[0] = 'test'
console.log(arr); // ["a", "b", "c"]
console.log(arrCopy); // ["test", "b", "c"]
concat
var arr = ['a', 'b', 'c'];
var arrCopy = arr.concat();
arrCopy[0] = 'test'
console.log(arr); // ["a", "b", "c"]
console.log(arrCopy); // ["test", "b", "c"]
知识点补充:
arrayObj.slice(start, [end]) 该方法返回一个 Array 对象,其中包含了 arrayObj 的指定部分。不会改变原数组
arrayObj.concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
其实也就是下面这么个意思。。。但还是用上面的方法来实现比较简单高效些
function deepCopy(arr1, arr2) {
for (var i = 0; i < arr1.length; ++i) {
arr2[i] = arr1[i];
}
}