JS深拷贝和浅拷贝

浅拷贝和深拷贝

先说数据类型,因为深浅拷贝与数据类型有关,数据类型分为基本数据类型(String、Number、Boolean、Null、Undefined、Symbol (es6引入的一种类型) )和引用数据类型(Object、Array、Function)。基本数据类型特点:直接存储在栈中;引用数据类型:它真实的数据是存储在堆内存中,栈中存储的只是指针,指向在堆中的实体地址。

浅拷贝

浅拷贝是指将一个对象的引用复制到另一个对象中,两个对象共享同一块内存空间。当修改其中一个对象时,另一个对象也会受到影响。

如何进行浅拷贝

可以使用 Object.assign 或者展开运算符 ... 来进行浅拷贝。

// 使用 Object.assign 进行浅拷贝
const obj1 = { a: 1, b: 2 };
const obj2 = Object.assign({}, obj1);
obj2.a = 3;
console.log(obj1); // 输出:{ a: 1, b: 2 }
console.log(obj2); // 输出:{ a: 3, b: 2 }
// 所以大家觉得assign是深拷贝了? no no no~,接着往下看
let source = { a: { b : 1 }, c: 1 };
let target = Object.assign({}, source);
console.log(target)  // { a: { b: 1 }, c: 1 }

source.a.b = 2;
source.c = 3
console.log(source)  // { a: { b: 2 }, c: 3 }
console.log(target)  // { a: { b: 2 }, c: 1 }
神奇的事情发生了,target.a.b的值随着source变化而变化,但是target.c的值并没有随着source变化
// 使用展开运算符进行浅拷贝也是一样的道理
const obj3 = { a: 1, b: 2 };
const obj4 = { ...obj3 };
......

深拷贝

深拷贝是指创建一个新的对象,将原始对象的所有属性复制到新对象中,如果属性是基本类型,则直接复制,如果属性是引用类型,则递归地进行深拷贝。

如何进行深拷贝

可以使用 JSON 序列化和反序列化的方式实现深拷贝。也可以使用第三方库,如 lodash 的 cloneDeep 方法来进行深拷贝。

// 使用 JSON 实现深拷贝
const obj5 = { a: 1, b: { c: 2 } };
const obj6 = JSON.parse(JSON.stringify(obj5));
obj6.b.c = 3;
console.log(obj5); // 输出:{ a: 1, b: { c: 2 } }
console.log(obj6); // 输出:{ a: 1, b: { c: 3 } }

// 使用第三方库实现深拷贝
const _ = require('lodash');
const obj7 = { a: 1, b: { c: 2 } };
const obj8 = _.cloneDeep(obj7);
obj8.b.c = 3;
console.log(obj7); // 输出:{ a: 1, b: { c: 2 } }
console.log(obj8); // 输出:{ a: 1, b: { c: 3 } }

浅拷贝和深拷贝的区别

浅拷贝只复制对象的引用,两个对象共享同一块内存空间。当修改其中一个对象时,另一个对象也会受到影响。而深拷贝则是创建一个新的对象,将原始对象的所有属性复制到新对象中,因此,对深拷贝后的对象进行修改不会影响原始对象。

在实际开发中,需要根据具体情况选择使用浅拷贝还是深拷贝。如果只是想复制对象的属性,并且不会修改属性值,则可以使用浅拷贝。如果需要对复制后的对象进行修改,并且不希望影响原始对象,则需要使用深拷贝。

你可能感兴趣的:(JS基础,Vue,实际开发常见问题,javascript,开发语言,ecmascript,前端,面试)