- 场景
let obj1 = { name: "bello", age: 18, sayHello: function () { console.log("你好呀"); }, details: { height: "180cm", weight: "70kg", hobby: ["打游戏", "跑步", "看电影"], }, }; let obj2 = obj1; obj2.age = 20; console.log("obj1", obj1); console.log("obj2", obj2);上面例子中,把 obj1 的内容赋值给 obj2,当修改obj2 中属性 age 值为20后,打印结果如下:
发现 obj1 中的 age 值也变成了 20,这是因为当我们将变量赋值给另外一个变量时,复制的是原本变量的地址(指针),即 obj1 和 obj2 同时引用了同一个内存地址,当我们进行数据修改的时候,就会修改存放在地址(指针),也就导致了两个变量的值都发生了改变。
所以为了解决上面的问题就得使用深浅拷贝
- 浅拷贝
还是以上面场景为例:
let obj1 = { name: "bello", age: 18, sayHello: function () { console.log("你好呀"); }, details: { height: "180cm", weight: "70kg", hobby: ["打游戏", "跑步", "看电影"], }, }; // 为了实现修改 obj2 中的属性值不会影响 obj1, // 可以循环 obj1 将每个属性挨个添加给 obj2 let obj2 = {}; for (var key in obj1) { obj2[key] = obj1[key]; } obj2.age = 20; console.log("obj1", obj1); console.log("obj2", obj2);运行代码,我们再来看看结果:
修改 obj2 中的属性时,obj1中属性并没有变,这样就实现了一个浅拷贝功能
- 深拷贝
其实浅拷贝在大部分场景下都能胜任需求了,但是到遇到数据比较复杂,对象拥有多层嵌套时这样还是会出问题。
我们还是以上面为例:
let obj1 = { name: "bello", age: 18, sayHello: function () { console.log("你好呀"); }, details: { height: "180cm", weight: "70kg", hobby: ["打游戏", "跑步", "看电影"], }, }; // 如果要修改 details 中属性时 let obj2 = {}; for (var key in obj1) { obj2[key] = obj1[key]; } obj2.details.weight = "80kg"; console.log("obj1", obj1); console.log("obj2", obj2);当修改 obj2 深层属性 weight 时,结果如下图
obj1 中的 weight 属性值同步也被改变了,不难发现这是因为 循环 obj1 时,仅仅只是将 obj1 中的第一层属性添加在 obj2 上,而更深一层的 weight 属性并没有单独拿出来给 obj2 ,所以也就导致了 obj1 和 obj2 中 weight 属性依然指向同一个地址
那么解决这个问题可以使用递归的思想,在循环的时候挨个判断每个属性,如果是引用数据类型(Object,Array)就再次循环赋值
依然以上面为例: let obj1 = { name: 'bello', age: 18, sayHello: function () { console.log('你好呀') }, details: { height: '180cm', weight: '70kg', hobby: ['打游戏', '跑步', '看电影'] } } function colp(obj) { let newObj = {} for (let key in obj) { if (typeof obj[key] == 'object' && obj[key] != null) { newObj[key] = colp(obj[key]) } else { newObj[key] = obj[key] } } return newObj } let obj2 = colp(obj1) obj2.details.weight = '80kg' console.log('obj1', obj1) console.log('obj2', obj2)打开控制台,结果真的 Amazing 啊!obj1的weight属性值并没有改变
这样就实现了一个简单的深拷贝啦