深拷贝与浅拷贝的区别就在于,修改原值时,拷贝的值是否会发生改变,改变了就是浅拷贝,不改变就是深拷贝。
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址。
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。
深拷贝就像A的房子里有一样东西,B就去买了房子,也放进去了同样的东西,所以当A在房子里拿走或放入东西时,B的房子不会发生变化。
浅拷贝就像A的房子里有一样东西,A把房子的地址告诉了B,所以当A在房子里拿走或放入东西时,B一去看也知道这所房子里的东西了。
深拷贝实现方法
JSON.parse(JSON.stringify())
let list = [];
let arr = [
{
id: 1,
canClick: true,
content: ''
},
{
id: 2,
canClick: true,
content: ''
},
{
id: 3,
canClick: true,
content: ''
}];
list = arr.map(obj => (
{ ...obj }
)); // 深拷贝
浅拷贝实现方法
- Object.assign()
Object.assign()进行的是浅拷贝,拷贝的是对象属性的引用,而不是对象本身。
var source = {
obj: { a: '哈哈哥', b: 40 },
};
var target = Object.assign({}, source);
target.obj.a = '嘿嘿哥';
target.obj.b = 50;
console.log(source); // { obj: { a: '嘿嘿哥', b: '50' } }
console.log(target); // { obj: { a: '嘿嘿哥', b: '50' } }
当Object.assign()对只有一层基本数据类型进行拷贝时,相当于深拷贝:
const source= { a: 1, b: 2 };
const target = Object.assign({}, source);
target.a = 111;
target.b = 222;
console.log(source); // { a: 1, b: 2 }
console.log(target); // { a: 111, b: 222 }
- Array.prototype.concat()
concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
var source = [1, 2, { name: 'CSDN', age: 21 }];
var target = source.concat();
target[0] = 100;
target[2].name = 'csdn';
console.log(source); // [1, 2, { name: 'csdn', age: 21 }];
console.log(target); // [100, 2, { name: 'csdn', age: 21 }];
- Array.prototype.slice()
slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
var source = [1, 2, { name: 'CSDN', age: 21 }];
var target = source.slice();
target[0] = 100;
target[2].name = 'csdn';
console.log(source); // [1, 2, { name: 'csdn', age: 21 }];
console.log(target); // [100, 2, { name: 'csdn', age: 21 }];
Array的slice和concat方法不修改原数组(source),只会返回一个浅拷贝了原数组(source)中元素的一个新数组(target)。当修改新数组(target)中的基本类型值时,原数组(source)中的基本类型值不会改变,当修改新数组(target)中的引用类型值时,原数组(source)中的引用类型值也会被修改。
拷贝代码实现部分参考了 js中深拷贝与浅拷贝解析这篇文章。