一、JS的数据类型
要想学习深浅拷贝,首先需要了解javascript的数据类型
javascript 中有两种数据类型,分别是基本数据类型(Number、String、Undefined、Boolean、Null、Symbol)和引用数据类型(对象、数组、函数)。
基本数据类型是按值访问的,操作的就是变量保存的值;如果是引用类型,则是通过保存在变量中的引用类型的地址来操作实际对象。
基本类型是不可变的,任何方法都无法改变一个基本类型的值,也不可以给基本类型添加属性或者方法。但是可以为引用类型添加属性和方法,也可以删除其属性和方法。
下面请看示例:
let num1 = 10; let obj1 = { name: "ding" } let num2 = num1; let obj2 = obj1; num2 = 20; obj2.name = "bai"; console.log(num1); // 10 console.log(obj1.name); // bai
可以看出赋值的时候,基本类型是在栈内存中重新开辟内存,存放变量num2,所以在栈内存中存放的基本数据类型是不会相互影响的。引用类型复制的只是引用地址,指向的是堆内存中同一地址的同一对象,修改时会相互影响。
所以对于基本类型的拷贝,并没有深浅拷贝的区别,我们所说的深浅拷贝都是对于引用类型而言的。
二、浅拷贝
浅拷贝的意思就是只复制引用,而未复制真正的值,源对象和目标对象共享同一块内存,一个修改时另一个也跟着修改。上述代码就是利用 = 赋值操作实现的浅拷贝。也可以利用Object.assign或展开运算符 ... 来实现浅拷贝。
通过 Object.assign 实现,Object.assign第一级属性深拷贝,以后级别属性浅拷贝。
let a = { age: 1, name: { asd: "123" } }; let b = Object.assign({}, a); b.age = 2; b.name.asd = "456"; console.log(a.age, a.name.asd); //1 ‘456’
通过展开运算符 ... 来实现深拷贝,但是需要注意的是,只针对对象的第一级属性有效
var arr = { name: "aaa", other: { name: "bbb" } }; var arr2 = { ...arr }; arr2.name = "AAA"; arr2.other.name = "BBB"; console.log(arr); // { name: 'aaa', other: { name: 'BBB' } } console.log(arr2); // { name: 'AAA', other: { name: 'BBB' } }
三、深拷贝
深拷贝实现的是真正意义上的对象的拷贝。深拷贝会创造一个一模一样的对象,其内容地址是自助分配的,拷贝结束之后,内存中的值完全相同,但是内存地址是不一样的,目标对象跟源对象不共享内存,修改任何一方的值,不会对另外一方造成影响。
可以通过JSON.parse(JSON.stringify(object))实现深拷贝:
var arr = { name: "aaa", other: { name: "bbb" } }; var arr2 = JSON.parse(JSON.stringify(arr)); arr2.name = "AAA"; arr2.other.name = "BBB"; console.log(arr); // { name: 'aaa', other: { name: 'bbb' } } console.log(arr2); // { name: 'AAA', other: { name: 'BBB' } }
实现原理:拷贝一个字符串会开辟一个新的存储地址,这样就切断了引用对象的指针联系,所以先转成一个字符串,在解析出对象,这样就可以深拷贝一个对象 。
补充:
JSON.parse(str) 用于从一个字符串中解析出 json 对象,JSON.stringify(obj)用于从一个对象解析出字符串。
自己实现一个深拷贝函数:
function deepClone(obj) { let res; if (typeof obj === 'object') { if (obj === null) { res = obj; } else { res = Array.isArray(obj) ? [] : {}; for (let key in obj) { let val = obj[key]; res[key] = deepClone(val); } } } else { // 除了数组和对象之外的类型 res = obj; } return res; }
验证:
let obj = { a: { name: '小明' }, b: 111, c: [1,2,3,4], d: '你好', e: null, f: function() {} }; let b = deepClone(obj); obj.a.name = 222; console.log(obj,b);
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212962.html原文链接:https://javaforall.net
