我理解的浅拷贝和深拷贝
Posted garfieldzhong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我理解的浅拷贝和深拷贝相关的知识,希望对你有一定的参考价值。
浅拷贝:通过一个对象来创建一个新对象,如果对象的属性的值是基本数据类型,直接把值赋给新对象,如果值是引用类型则把数据的对应的内存地址赋给新对象;因为两个对象对应的是同一个内存地址,当其中一个对象数据改变了,就相当于改变了内存地址,所以会影响到别一个对象;
深拷贝:通过一个对象来创建一个新对象,无论基本类型还是引用类型都将值赋给新对象,引用类型会开辟一块新的内存地址用于存放数据,因为不会相互影响;
浅拷贝的方法:
1.直接赋值:
var obj1 = {a: 1, b: 2}; var obj2 = obj1; obj2.b = 22; console.log(obj1.b); // 22
2.Object.assign
var obj1 = {a: 1, b: 2}; var obj2 = {c: 3}; Object.assign(obj1, obj2); console.log(obj1) // {a: 1, b: 2, c: 3} obj2.c = 4; console.log(obj1.c) // 3
乍一看,这貌似两个对象互不影响了!难道是深拷贝了?
var obj1 = {a: 1, b: 2}; var obj2 = {c: {z: 3}}; Object.assign(obj1, obj2); console.log(obj1); // {a: 1, b: 2, c: {z: 3}} console.log(obj2); // {c: {z: 3}} obj2.c.z = 4; console.log(obj1.c.z); // 4;
由些可见,Object.assign只是对第一层数据进行了深拷贝,实际上依然是一个浅拷贝。
3.通过对象扩展运算符 ({ ...obj })
var obj1 = { a: 1, b: 2, c: { z: 3 } }; var obj2 = {...obj1}; console.log(obj2); // { a: 1, b: 2, c: { z: 3 } } obj1.a = 11; console.log(obj2.a); // 1 obj1.c.z = 33; console.log(obj2.c.z); // 33
由此可见...扩展运算符跟assign一样也是浅拷贝。
4.通过数组的slice方法
var arr1 = [1, [2, 3], 4]; var arr2 = arr1.slice(); console.log(arr2); // [1, [2, 3], 4] arr1[0] = 11; console.log(arr2[0]); // 1; 貌似深拷贝了,但是: arr1[1][0] = 22; console.log(arr2); // [1, [22, 3], 4; 还是太年轻啊!!!
5.通过数组的concat方法。
var arr1 = [1, [2, 3], 4]; var arr2 = arr1.concat(); console.log(arr2); // [1, [2, 3], 4] arr1[0] = 11; console.log(arr2[0]); // 1; arr1[1][0] = 22; console.log(arr2[1][0]); // 22
深拷贝的方法:
1. JSON.stringify() + JSON.parse();
原理是:把一个对象序列化成为一个JSON字符串,将对象的内容转换成字符串的形式再保存在磁盘上,再用JSON.parse()反序列化将JSON字符串变成一个新的对象;
var obj1 = { a: 1, b: 2, c: { z: 3 } }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(obj2); // {a: 1, b: 2, c: {z: 3}}
obj1.c.z = 33;
console.log(obj2.c.z); // 3
由此可见,已经实现了深拷贝!
但是,JSON.stringify()有个问题:无法拷贝函数、undefined、Symbol值,因为其在序列化时会忽略这些值;
var obj1 = { a: 1, b: ‘b‘, c: [1,2,3], u: undefined, s: Symbol(‘s‘), f: function() { console.log(123); } }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(obj2); // {a: 1, b: ‘b‘, c: [1, 2, 3]}
2.递归:
var deepCopy = function(obj) { if (typeof obj !== ‘object‘) return; var newObj = obj instanceof Array ? [] : {}; for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === ‘object‘ ? deepCopy(obj[key]) : obj[key]; } } return newObj; }
以上是关于我理解的浅拷贝和深拷贝的主要内容,如果未能解决你的问题,请参考以下文章