【JS】中深拷贝浅拷贝的区别和实现方式

本文介绍了JavaScript中深拷贝和浅拷贝的概念,浅拷贝只复制第一层,而深拷贝会创建全新的对象副本。提到了实现浅拷贝的方法如Object.assign、扩展运算符和slice,以及深拷贝的实现方式,包括JSON.parse和JSON.stringify结合、递归拷贝以及使用Lodash库的_.cloneDeep方法。文章还指出了深拷贝在处理复杂对象时的注意事项和限制。

1、概念

  1. 赋值不属于拷贝
  2. JS的 深拷贝浅拷贝主要作用于多层数组或对象中,其中:

浅拷贝:

只对第一层 数组或对象进行复制,其它层复制的是原存储的内存地址(修改其它深层级会影响原对象)

深拷贝:

构造一个新的复合数组或对象,每一层级 都在堆内存中开辟了新的空间,与原数组或对象互相不影响。

2、实现方式

浅拷贝的实现方式:

  1. 针对对象:使用 Object.assign() 方法,例如:let newObj = Object.assign({}, oldObj);
  2. 针对数组或对象:使用扩展运算符(...)进行浅复制,例如:let newObj = {…oldObj};let newArr = […oldArr];
  3. 针对数组:使用数组的 slice() 方法进行浅复制,例如:let newArray = oldArray.slice()

深拷贝的实现方式

  1. JSON.parse(JSON.stringfy(obj))
    JSON.parse(JSON.stringify(obj)):将对象序列化为 JSON 字符串,再将字符串解析为新的对象。这种方式可以实现深拷贝,但有一些限制,例如无法复制函数、循环引用等不可序列化的属性;
  2. 手动递归拷贝
    使用递归的方式遍历对象的属性,逐一复制到新的对象中。这种方式可以实现深拷贝,但需要手动编写代码,并且不适用于嵌套层数较深的对象。
// 递归实现深拷贝
function deepClone(obj) {
 if (typeof obj !== 'object' || obj === null) {
   return obj;
 }
 let newObj = Array.isArray(obj) ? [] : {};
 for (let key in obj) {
   newObj[key] = deepClone(obj[key]);
 }
 return newObj;
}
  1. Lodash 的 _.cloneDeep() (使用第三方库)
    可以实现深拷贝,支持复制函数、循环引用等特殊属性,使用方便;
### JavaScript深拷贝浅拷贝区别实现方式 #### 深拷贝浅拷贝的概念 在 JavaScript 编程中,深拷贝浅拷贝是两个常用的概念。它们涉及到在复制对象或数组时如何处理内部数据的问题。浅拷贝仅复制对象的第一层属性,而深拷贝会递归地复制对象的所有层级属性[^1]。 - 浅拷贝:当修改其中一个对象时,另一个对象可能受到影响,因为它们共享相同的引用。 - 深拷贝:当修改其中一个对象时,另一个对象不会受到影响,因为它们是完全独立的副本。 #### 浅拷贝实现方式 浅拷贝可以通过多种方法实现,例如使用 `Object.assign()` 或扩展运算符(`...`)。这些方法只会复制对象的第一层属性,嵌套的对象仍然共享引用。 ```javascript const obj1 = { a: 1, b: { c: 2 } }; const shallowCopy = Object.assign({}, obj1); shallowCopy.b.c = 3; console.log(obj1.b.c); // 输出:3,说明这是浅拷贝 ``` #### 深拷贝实现方式 深拷贝可以通过以下几种方法实现: 1. **使用 `JSON.parse(JSON.stringify(obj))`** 这种方法通过将对象序列化为 JSON 字符串,然后再将其解析回对象来实现深拷贝。然而,这种方法不适用于包含函数、`undefined`、`Symbol` 或循环引用的对象[^2]。 ```javascript const original = { a: 1, b: { c: 2 } }; const deepCopied = JSON.parse(JSON.stringify(original)); deepCopied.b.c = 3; console.log(original.b.c); // 输出:2 console.log(deepCopied.b.c); // 输出:3 ``` 2. **使用递归函数** 递归方法可以处理复杂的嵌套对象,并且能够解决循环引用问题。以下是一个示例实现: ```javascript function deepClone(obj, hash = new WeakMap()) { if (obj === null) return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (typeof obj !== "object") return obj; if (hash.has(obj)) return hash.get(obj); let cloneObj = Array.isArray(obj) ? [] : {}; hash.set(obj, cloneObj); for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key], hash); } } return cloneObj; } ``` 这种方法可以确保所有层级的属性都被独立复制,并且能够处理循环引用[^3]。 3. **使用第三方库** Lodash 提供了一个简单易用的深拷贝方法 `cloneDeep`,它可以处理各种复杂的数据结构,包括循环引用特殊类型(如 `Map` `Set`)。 ```javascript const _ = require('lodash'); const original = { a: 1, b: { c: 2 } }; const deepCopied = _.cloneDeep(original); deepCopied.b.c = 3; console.log(original.b.c); // 输出:2 console.log(deepCopied.b.c); // 输出:3 ``` #### 示例代码 以下是一个综合示例,展示如何使用递归方法进行深拷贝: ```javascript const original = { a: 1, b: { c: 2, d: [3, 4] }, e: new Set([5, 6]), f: new Map([[7, 8]]) }; const deepCopied = deepClone(original); deepCopied.b.c = 99; deepCopied.e.add(100); deepCopied.f.set(11, 12); console.log(original.b.c); // 输出:2 console.log(original.e.has(100)); // 输出:false console.log(original.f.has(11)); // 输出:false ``` #### 总结 深拷贝浅拷贝的主要区别在于是否递归地复制对象的所有层级属性。浅拷贝只复制第一层属性,而深拷贝确保所有层级的属性都被独立复制。深拷贝可以通过多种方法实现,包括 `JSON.parse(JSON.stringify(obj))`、递归函数以及第三方库如 Lodash 的 `cloneDeep` 方法[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值