Skip to content

浅拷贝和深拷贝

浅拷贝和深拷贝的区别

>[!note] 核心区别 是否拷贝引用对象的嵌套内容(如子对象)


1. 浅拷贝

定义

浅拷贝是指创建一个新的对象或数组,但它只复制第一层属性值,对于嵌套的引用类型(如对象或数组),浅拷贝只拷贝它们的引用,而不是实际内容。

特性

  • 浅拷贝后的对象或数组共享嵌套引用类型的内容
  • 修改嵌套的引用类型会影响原始对象。

浅拷贝实现方式

1. Object.assign()

Object.assign() 静态方法将一个或者多个 源对象 中所有可枚举自有属性复制到 目标对象 ,并返回修改后的目标对象。

js
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, obj);
shallowCopy.b.c = 42;
console.log(obj.b.c); // 输出: 42 (修改影响了原对象)
2. 扩展运算符(...

扩展运算符(...)是 JavaScript 中引入的一种语法糖,用来展开数组、对象或可迭代对象的元素。它最早在 ES6 中引入,极大地简化了数据操作的代码。

js
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.b.c = 42;
console.log(obj.b.c); // 输出: 42
3. Array.prototype.slice()(对于数组)
javascript
const arr = [1, 2, [3, 4]];
const shallowCopy = arr.slice();
shallowCopy[2][0] = 42;
console.log(arr[2][0]); // 输出: 42

2. 深拷贝

定义

深拷贝是指创建一个新的对象或数组,同时递归地拷贝 所有 嵌套的引用类型内容,确保新对象与原对象完全独立

特性

  • 深拷贝后,两个对象完全独立,修改一个不会影响另一个。
  • 所有嵌套的引用类型都会被递归复制。

深拷贝实现方式

1. JSON.parse(JSON.stringify())

适用于简单的对象或数组(不包含 函数、undefinedSymbol等)。 原理:

  1. 首先将需要被拷贝的对象转换成字符串
  2. 再解析json字符串
javascript
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 42;
console.log(obj.b.c); // 输出: 2 (原对象未被修改)

局限性

  • 无法拷贝函数、undefinedSymbol
  • 不支持循环引用(即对象内部有引用自身的情况)。
2. 递归拷贝

手动实现一个深拷贝函数:

javascript
function deepClone(obj) {
  //1. 如果是基本类型直接返回
  if (obj === null || typeof obj !== 'object') { 
    return obj; //null是基本类型,但是type是object,历史遗留问题
  }
  
  //2.创建obj的同类型副本copy
  const copy = Array.isArray(obj) ? [] : {};

  //3.将obj的对象循环遍历拷贝到copy中
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {  // hasOwnProperty(key)判断key是否是obj的属性
      copy[key] = deepClone(obj[key]); // 递归拷贝
    }
  }
  return copy;
}

const obj = { a: 1, b: { c: 2 } };
const deepCopy = deepClone(obj);
deepCopy.b.c = 42;
console.log(obj.b.c); // 输出: 2
3. 使用库

Lodash 的 _.cloneDeep 是常用的深拷贝工具:

javascript
const _ = require('lodash');
const obj = { a: 1, b: { c: 2 } };
const deepCopy = _.cloneDeep(obj);
deepCopy.b.c = 42;
console.log(obj.b.c); // 输出: 2

3. 浅拷贝和深拷贝的区别

特性浅拷贝深拷贝
拷贝层级第一层所有层级
嵌套引用类型引用具体内容
对象间的独立性共享嵌套的引用类型,可能会互相影响完全独立
适用场景对象嵌套层级较浅,性能要求较高时对象嵌套层级较深,需要绝对独立时
实现难度简单(如 Object.assign复杂(如递归或库支持)

4. 选择使用的场景

  • 浅拷贝
    • 当对象层级较浅时,浅拷贝性能更高。
    • 如果不需要嵌套属性的独立性,可以使用浅拷贝。
    • 示例:用于简单对象或配置项的复制。
  • 深拷贝
    • 当对象层级较深且需要完全独立时,必须使用深拷贝。
    • 示例:复制复杂的数据结构(如树、嵌套数组)。

通过理解浅拷贝和深拷贝的区别和适用场景,能帮助我们更好地处理 JavaScript 中的数据操作问题。

评论区

欢迎留言、补充或勘误。

xiaoba.blog