JavaScript深拷贝与浅拷贝的区别

人工智能梦工厂 2020-06-02 ⋅ 17 阅读

在 JavaScript 中,拷贝一个变量或对象是非常常见的操作。然而,拷贝操作涉及到的细节却有很多不同的方法,其中最为重要的区别是"深拷贝"和"浅拷贝"。本文将介绍这两种拷贝方式的区别以及它们在 JavaScript 中的应用。

1. 浅拷贝

浅拷贝是指创建一个新的对象或数组,将原始对象或数组的引用复制给新对象,而不是复制它们的内容。换句话说,浅拷贝只是拷贝了引用,而不是拷贝了值本身。

在 JavaScript 中,可以使用多种方式进行浅拷贝:

1.1 Object.assign()

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。这个方法可以用于浅拷贝对象。

let obj1 = { foo: 'bar' };
let obj2 = Object.assign({}, obj1);

obj1.foo = 'baz';

console.log(obj1); // 输出: { foo: 'baz' }
console.log(obj2); // 输出: { foo: 'bar' }

1.2 扩展运算符

扩展运算符 ... 可以展开一个对象或数组。对于对象来说,展开操作会创建一个新的对象,将原始对象的属性的副本复制到新对象中。

let obj1 = { foo: 'bar' };
let obj2 = { ...obj1 };

obj1.foo = 'baz';

console.log(obj1); // 输出: { foo: 'baz' }
console.log(obj2); // 输出: { foo: 'bar' }

2. 深拷贝

深拷贝是指创建一个新的对象或数组,并递归地将原始对象或数组的所有属性或元素的值复制给新对象。换句话说,深拷贝不仅拷贝了引用,还拷贝了值本身。

在 JavaScript 中,实现深拷贝需要考虑到对象或数组的嵌套结构。以下是几种实现深拷贝的方法:

2.1 JSON.parse() 和 JSON.stringify()

通过将对象或数组转换为 JSON 字符串,然后再把 JSON 字符串转换为新的对象或数组,可以达到深拷贝的效果。

let obj1 = { foo: { bar: 'baz' } };
let obj2 = JSON.parse(JSON.stringify(obj1));

obj1.foo.bar = 'qux';

console.log(obj1); // 输出: { foo: { bar: 'qux' } }
console.log(obj2); // 输出: { foo: { bar: 'baz' } }

需要注意的是,使用 JSON.parse() 和 JSON.stringify() 的深拷贝方法有一些限制,例如不能拷贝函数、正则表达式、循环引用等特殊类型。

2.2 递归拷贝

递归拷贝是一种自定义的深拷贝方法,通过递归地遍历对象或数组的每个属性或元素,并对其进行拷贝,来实现深拷贝的效果。

以下是一个简单的递归拷贝函数的示例:

function deepCopy(obj) {
  if (typeof obj !== 'object') {
    return obj;
  }

  let newObj = Array.isArray(obj) ? [] : {}; // 判断是对象还是数组

  for (let key in obj) {
    newObj[key] = deepCopy(obj[key]); // 递归拷贝每个属性或元素
  }

  return newObj;
}

let obj1 = { foo: { bar: 'baz' } };
let obj2 = deepCopy(obj1);

obj1.foo.bar = 'qux';

console.log(obj1); // 输出: { foo: { bar: 'qux' } }
console.log(obj2); // 输出: { foo: { bar: 'baz' } }

递归拷贝是一种通用且可靠的深拷贝方法,但其性能可能不如其他方法。

总结

深拷贝和浅拷贝是 JavaScript 中常见的拷贝方式,它们之间的区别在于是否拷贝了值本身。浅拷贝只是拷贝了引用,而深拷贝通过递归地拷贝所有属性或元素的值来实现完全的拷贝。在实际使用中,可以根据需求选择适合的拷贝方式。


全部评论: 0

    我有话说: