关于对象的拷贝

当你复制一个对象时,浅拷贝和深拷贝指的是复制过程中是否复制了对象内部的引用。

浅拷贝(Shallow Copy)

浅拷贝创建了一个新对象,这个新对象有着原始对象属性值的一份精确拷贝。但对于原始对象中的嵌套对象或数组等引用类型的属性,浅拷贝只会复制它们的引用而不是创建新的引用。因此,如果原始对象内的引用类型属性发生变化,浅拷贝后的对象也会受到影响。

const obj = { a: 1, b: { c: 2 } };

// 浅拷贝
const shallowCopy = Object.assign({}, obj);

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(shallowCopy); // 输出: { a: 1, b: { c: 200 } },原对象属性变化会影响浅拷贝

在上面的例子中,shallowCopyobj 的浅拷贝,当修改了 obj 的属性值时,shallowCopy 也受到了影响,因为它们共享相同的引用类型属性。

深拷贝(Deep Copy)

深拷贝创建了一个全新的对象,它将原始对象内部的所有属性都复制了一份,包括嵌套对象和数组等引用类型的属性。换句话说,深拷贝不仅复制了对象本身,还会递归地复制所有引用类型的属性,确保创建的对象与原始对象完全独立,互不影响。

const obj = { a: 1, b: { c: 2 } };

// 深拷贝
const deepCopy = JSON.parse(JSON.stringify(obj));

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(deepCopy); // 输出: { a: 1, b: { c: 2 } },原对象属性变化不会影响深拷贝

在这个例子中,deepCopyobj 的深拷贝。即使修改了 obj 的属性值,deepCopy 也不受影响,因为它们是独立的对象。JSON.parse(JSON.stringify(obj)) 是一个简单的深拷贝方法,但它有一些限制,无法复制函数、正则表达式等特殊类型的属性。

                浅拷贝对象 

使用 Object.assign()

const obj = { a: 1, b: { c: 2 } };

// 使用 Object.assign() 进行浅拷贝
const shallowCopy = Object.assign({}, obj);

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(shallowCopy); // 输出: { a: 1, b: { c: 200 } },原对象属性变化会影响浅拷贝

使用扩展运算符 ...

const obj = { a: 1, b: { c: 2 } };

// 使用扩展运算符进行浅拷贝
const shallowCopy = { ...obj };

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(shallowCopy); // 输出: { a: 1, b: { c: 200 } },原对象属性变化会影响浅拷贝

无论使用哪种方式,它们都能够创建一个新对象,并复制原对象的属性。但需要注意的是,如果原对象的属性值是引用类型(如对象或数组),浅拷贝只会复制引用,而不是创建新的引用。这意味着对于原对象中的嵌套对象或数组,修改它们的属性值会影响浅拷贝后的对象。

手动复制属性

const obj = { a: 1, b: { c: 2 } };
const shallowCopy = {};

for (let key in obj) {
  shallowCopy[key] = obj[key];
}

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(shallowCopy); // 输出: { a: 1, b: { c: 200 } },原对象属性变化会影响浅拷贝

这种方法使用 for...in 循环遍历原对象的属性,并将其复制到新对象中。然而,和其他浅拷贝方式一样,对于原对象中的引用类型属性,仅复制了引用而不是创建新的引用。

使用 Object.create()

const obj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.create(obj);

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(shallowCopy); // 输出: {},原对象属性变化不会影响浅拷贝

Object.create() 方法创建了一个新对象,并将原对象作为新对象的原型。这样创建的新对象是一个空对象,并不直接包含原对象的属性。对原对象的属性的更改不会影响到使用 Object.create() 创建的新对象,但是需要注意,它只能复制原对象的原型链上的属性。

上述方法比较常见,也有别的方法就不一一例举了!!

 浅拷贝一个单层对象通常可以使用  Object.assign() 或者 扩展运算符 ... 

深拷贝对象

使用 JSON 方法(适用于部分场景)

const obj = { a: 1, b: { c: 2 } };

// 使用 JSON 方法进行深拷贝
const deepCopy = JSON.parse(JSON.stringify(obj));

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(deepCopy); // 输出: { a: 1, b: { c: 2 } },原对象属性变化不会影响深拷贝

使用递归实现深拷贝

function deepClone(obj, clonedObjects = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') {
    return obj; // 如果是原始值或者 null,直接返回
  }

  // 避免循环引用
  if (clonedObjects.has(obj)) {
    return clonedObjects.get(obj);
  }

  // 处理对象或数组
  const clone = Array.isArray(obj) ? [] : {};

  // 将新对象存入 WeakMap,避免循环引用导致的无限递归
  clonedObjects.set(obj, clone);

  // 递归复制每个属性
  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      clone[key] = deepClone(obj[key], clonedObjects);
    }
  }

  return clone;
}

这个 deepClone 函数可以递归地复制对象及其嵌套属性,确保创建的是原对象的完全独立拷贝。这种方法相对较为复杂,但能够处理对象中的各种情况,包括嵌套对象和数组的深度拷贝。

lodash 库中的 _.cloneDp()ee 方法

除了使用递归和 JSON 方法外,还有其他一些库可以帮助进行深拷贝,比如 lodash 库中的 _.cloneDp()ee 方法。这个方法可以深度复制对象和数组,并处理循环引用。

npm install lodash

然后,使用 _.cloneDeep() 方法进行深拷贝:

const _ = require('lodash');

const obj = { a: 1, b: { c: 2 } };

// 使用 _.cloneDeep() 进行深拷贝
const deepCopy = _.cloneDeep(obj);

obj.a = 100; // 修改原对象属性值
obj.b.c = 200; // 修改原对象中的对象属性值

console.log(deepCopy); // 输出: { a: 1, b: { c: 2 } },原对象属性变化不会影响深拷贝

lodash 库提供了许多实用的函数,其中 _.cloneDeep() 是一个处理深度拷贝的方便方法。它可以帮助你避免编写自己的深拷贝函数,并提供了更多的功能来处理对象的拷贝。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值