📜  深拷贝 javascript (1)

📅  最后修改于: 2023-12-03 15:40:45.919000             🧑  作者: Mango

深拷贝 JavaScript

在 JavaScript 中,拷贝对象是一个非常常见的操作。不同的需求需要不同的拷贝方式,而其中最复杂的就是深拷贝。深拷贝不仅可以复制对象本身,还可以复制对象内部的所有嵌套对象,从而得到独立的新对象。正如这个实例所展示的,你和你的朋友在各自的电脑上打开了这篇文章,但是这篇文章不会因为你们两个之间的操作而相互影响,这就是深拷贝的好处。

什么是深拷贝?

深拷贝是指将指定对象及其中的所有嵌套对象都复制到一个新的独立对象中。也就是说,当你修改一个对象时,不会改变其他对象。这种方式非常安全,但是也可能很慢。

JavaScript 的浅拷贝

JavaScript 中有一种简单的拷贝方式称为浅拷贝。浅拷贝只会复制对象本身的属性,而不会复制它内部的对象。所以它们之间共享引用,对其中一个对象的修改也会影响到另外一个对象。下面是一个浅拷贝对象的例子。

const obj = {name: 'Tom', age: 18, location: {country: 'China', city: 'Shanghai'}};
const copyObj = {...obj}; // 浅拷贝对象

上面这段代码会创建一个新对象copyObj来存储obj的属性。但是当我们修改copyObjlocation属性时,objlocation属性也会发生相同的变化。

copyObj.location.country = 'Japan';
console.log(obj.location.country); // 'Japan'

这就是为什么我们需要深拷贝。

如何进行深拷贝?

在 JavaScript 中,有许多方法可以进行深拷贝。以下是三种流行的深拷贝方法:递归、深层克隆、JSON.parse()JSON.stringify()方法。

递归

递归是最基本也是最常见的深拷贝方法。在递归过程中,我们需要递归每个对象的属性,直到找到基本类型的属性。

function deepClone(obj) {
  let clonedObj = {};
  
  for (let prop in obj) {
    if (typeof obj[prop] === "object") {
      clonedObj[prop] = deepClone(obj[prop]);
    } else {
      clonedObj[prop] = obj[prop];
    }
  }
  
  return clonedObj;
}

const obj = {name: 'Tom', age: 18, location: {country: 'China', city: 'Shanghai'}};
const cloned = deepClone(obj); // 深拷贝对象

cloned.location.country = 'Japan';
console.log(obj.location.country); // 'China'
深层克隆

深层克隆实际上是通过序列化和解析对象来实现深拷贝的。这种方法需要将对象先转换为字符串,再将字符串解析成新的对象。下面是使用深层克隆进行深拷贝的代码:

function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

const obj = {name: 'Tom', age: 18, location: {country: 'China', city: 'Shanghai'}};
const cloned = deepClone(obj); // 深拷贝对象

cloned.location.country = 'Japan';
console.log(obj.location.country); // 'China'

这种方法非常好用,但是可能会遇到某些对象无法序列化的问题,如Date对象等。另外,由于它需要执行两个非常重的操作,因此可能在性能方面存在问题。

JSON.parse()JSON.stringify()方法

如果上面的方法不适合你的需求,那么可以使用JSON.parse()JSON.stringify()方法进行深拷贝。这种方法需要先将对象序列化成字符串,再将字符串重新解析为新对象。

function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

const obj = {name: 'Tom', age: 18, location: {country: 'China', city: 'Shanghai'}};
const cloned = deepClone(obj); // 深拷贝对象

cloned.location.country = 'Japan';
console.log(obj.location.country); // 'China'

这种方法的实现非常简洁,但是也会存在一些问题。首先,它会忽略函数、undefinedSymbol等属性。另外,它也无法拷贝循环引用的属性,因此可能会导致无限递归的问题。所以在使用这种方法时,需要格外小心。

总结

深拷贝是非常有用的,在处理一些复杂对象时尤为重要。使用递归、深层克隆、JSON.parse()JSON.stringify()方法都可以实现深拷贝,但是它们在性能、兼容性和易用性方面都存在各自的问题。因此在使用深拷贝时,需要根据实际需求进行选择,以达到最佳的效果。