先聊一聊什么是时浅拷贝, 什么又是深拷贝?
浅拷贝:
简单的说拷贝的是数据的地址; 这是相对于复杂数据类型而言. 因为复杂数据类型具有在内存的堆空间中创建空间的功能. 比如: { }, [ ], ( )
深拷贝:
它正好和浅拷贝对立, 从字面意思就知道; 更深层次的拷贝数据, 那么它拷贝的当然就是数据了, 而不是数据所在堆中的二进制地址了.
为什么会有浅拷贝和深拷贝的概念?
在日常的开发当中, "=" 赋值运算符是不可或缺的; 当我们将一个obj_one = obj_two的时候, 我们修改obj_one的值的时候, obj_two的值也会发生变化.
因为这样拷贝的是内存中的地址, 它们两个公用一个地址; 那么修改一个, 另外一个数据当然会被修改. 举个栗子:
<script>
let obj_one = {
name: '张三',
age: 20,
};
let obj_two = obj_one;
obj_two.name = '李四';
console.log(obj_one, obj_two);
</script>
如何实现深拷贝?
上述也就是浅拷贝带来的问题, 当然我能也不希望出现这样的问题; 所以实现深拷贝有两个方案:
(1)JSON
(2)递归
(1)使用JSON实现, 也是目前最为常见最简单实现深拷贝的方式
我们可以先使用JSON转换一下数据格式, 然后再次利用JSON提供的api再次转换回来.
<script>
let obj_one = {
name: '张三',
age: 20,
};
let obj_two = JSON.parse(JSON.stringify(obj_one));
obj_two.name = '李四';
obj_two.age = 18;
console.log(obj_one, obj_two);
</script>
因为JSON取出来的是只是单纯的数据, 而不是地址; 然后再将JSON的数据格式转换成js, { }有在堆中开空间的作用, 所以原数据不会发生改变.
(2)递归的方式来实现
<script>
function copy(obj, newobj) {
for (let key in obj) {
if (obj[key] instanceof Array) {
newobj[key] = [];
copy(obj[key], newobj[key]);
} else if (obj[key] instanceof Object) {
newobj[key] = {};
copy(obj[key], newobj[key]);
} else {
newobj[key] = obj[key];
};
};
};
let obj_one = {
name: '张三',
age: 20,
hobby: ['敲代码', '学习', '打游戏'],
girlfriend: {
name: '小美',
age: 22,
},
};
let obj_two = {};
copy(obj_one, obj_two);
obj_two.name = '李四';
obj_two.age = 18;
obj_two.hobby[1] = '学前端';
obj_two.girlfriend.name = '小丽';
console.log(obj_one, obj_two);
</script>