【js(8)js深拷贝和浅拷贝】
深拷贝和浅拷贝
- 一、引用类型的特性
- 二、浅拷贝
- 1.Object.assign() 实现浅拷贝
- 2. 展开运算符实现浅拷贝
- 3.使用Array.slice() 实现浅拷贝
- 4.使用Array.from() 实现浅拷贝
- 三、深拷贝
- 1.JSON 序列化/反序列化实现深拷贝
- 2. 手动递归实现深拷贝
- 3.使用第三方库实现深拷贝
一、引用类型的特性
js有基本类型的引用类型,区别:
- 基本类型(如 number、string、boolean):按值存储和传递,保存在栈内存中
- 引用类型(如 object、array、function):按引用存储和传递
- 引用类型数据保存在堆内存中,
- 引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中
let original = {name: "Alice",info: { age: 25 }};// 浅拷贝let shallowCopy = Object.assign({}, original);shallowCopy.info.age = 30;console.log(original.info.age); // 输出 30,因为 info 对象是共享的// 深拷贝let deepCopy = JSON.parse(JSON.stringify(original));deepCopy.info.age = 40;console.log(original.info.age); // 输出 25,原始对象未受影响
二、浅拷贝
- 浅拷贝创建一个新对象,但是只复制原始对象第一层属性的值
- 如果属性是基本类型,则复制其值
- 如果属性是引用类型,则复制其引用(地址)
1.Object.assign() 实现浅拷贝
const original = { name: "John", details: { age: 30 } };
const shallowCopy = Object.assign({}, original);shallowCopy.name = "Jane"; // 不影响原对象
shallowCopy.details.age = 25; // 影响原对象!console.log(original.name); // 输出: "John"
console.log(original.details.age); // 输出: 25
2. 展开运算符实现浅拷贝
const original = { name: "John", details: { age: 30 } };
const shallowCopy = { ...original };// 行为与 Object.assign() 相同
3.使用Array.slice() 实现浅拷贝
const originalArray = [1, 2, { value: 3 }];
const slicedArray = originalArray.slice();
4.使用Array.from() 实现浅拷贝
const fromArray = Array.from(originalArray);
三、深拷贝
- 深拷贝开辟一个新的栈,两个对象属性完全相同,但是对应两个不同的地址,
- 修改一个对象的属性,不会改变另一个对象的属性
1.JSON 序列化/反序列化实现深拷贝
- 简单但是有限制的方法
- 不能复制函数、undefined、Symbol、BigInt
- 不支持循环引用的对象
let obj = { a: 1, b: { c: 2 } };
let deepCopy = JSON.parse(JSON.stringify(obj));
2. 手动递归实现深拷贝
- 手动递归复制对象及其属性
- 直到所有属性都是基本数据类型为止
function deepClone(obj) {
//基本类型直接返回if (typeof obj !== 'object' || obj === null) {return obj;}const newObj = Array.isArray(obj) ? [] : {};for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = deepClone(obj[key]);}}return newObj;
}const originalObj = { name: 'John', age: 30, address: { city: 'Beijing', country: 'China' }
};const newObj = deepClone(originalObj);
newObj.address.city = 'Guangzhou';
console.log('originalObj:',originalObj);
console.log('newObj:',newObj);
3.使用第三方库实现深拷贝
- 如Loadsh、jQuery等
- 会增加项目的依赖和代码体积
const originalObj = { name: 'John', age: 30, address: { city: 'Beijing', country: 'China' }
};const newObj = _.cloneDeep(originalObj);
newObj.address.city = 'Guangzhou';
console.log(newObj);