JS实现深拷贝和浅拷贝的方式详解

关于JavaScript的深拷贝和浅拷贝,一般有如下几种实现方式:

浅拷贝

1. Object.assign() 方法

该方法用于将所有可枚举属性从一个或多个源对象复制到目标对象。如果源对象中有与目标对象相同的属性,那么目标对象对应属性的值将被覆盖。由于该方法只会进行浅拷贝,因此如果源对象中的属性是一个对象或数组等复合类型,那么目标对象和源对象的属性将会引用同一个对象。

const obj = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1, b: { c: 2 } }

copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }

copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 4 } } 对象的属性也被更改了。

2. 手写简易的浅拷贝函数

使用 for ... in 循环遍历原对象的所有可枚举属性,并将其复制到目标对象上。与 Object.assign() 类似,如果属性是一个对象或数组等复合类型,那么目标对象和源对象的属性将会引用同一个对象。

function shallowCopy(obj) {
  if (typeof obj !== 'object' || obj === null) return obj;
  const copy = Array.isArray(obj) ? [] : {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) copy[key] = obj[key];
  }
  return copy;
}

const obj = { a: 1, b: { c: 2 } };
const copy = shallowCopy(obj);
console.log(copy); // { a: 1, b: { c: 2 } }

copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }

copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 4 } } 对象的属性也被更改了。

深拷贝

1. JSON.parse + JSON.stringify

JSON.parse 方法用来解析 JSON 字符串,返回对应的 JavaScript 对象或值。JSON.stringify 方法用来将 JavaScript 对象或值转换为 JSON 字符串。

将一个对象进行深拷贝,可以先将对象转化成 JSON 字符串,再将其转化成对象,这样就可以获得一个与原对象完全独立的新对象。

需要注意的是,该方法只适用于对象的属性值是可遍历的,如果出现循环引用的情况,则会抛出异常。

const obj = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(obj));
console.log(copy); // { a: 1, b: { c: 2 } }

copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }

copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 2 } } 对象的属性没有被更改。

2. 递归实现深拷贝函数

对于一个对象来说,我们需要遍历对象的所有属性,如果属性是一个基本类型,直接赋值即可。如果属性是一个对象或数组等复合类型,那么就需要递归调用深拷贝函数,直到遍历完所有的属性。

function deepCopy(obj, memo = new WeakMap()) {
  if (typeof obj !== 'object' || obj === null) return obj;
  if (memo.has(obj)) return memo.get(obj);
  const copy = Array.isArray(obj) ? [] : {};
  memo.set(obj, copy);
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) copy[key] = deepCopy(obj[key], memo);
  }
  return copy;
}

const obj = { a: 1, b: { c: 2 } };
const copy = deepCopy(obj);
console.log(copy); // { a: 1, b: { c: 2 } }

copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }

copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 2 } } 对象的属性没有被更改。

以上介绍了针对JavaScript的深拷贝和浅拷贝的实现方式,建议在开发过程中根据实际场景选择合适的方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS实现深拷贝和浅拷贝的方式详解 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • postgres之jsonb属性的使用操作

    当使用PostgreSQL数据库时,我们有时需要存储JSON格式的数据。在PostgreSQL中,有两种类型的JSON数据:json和jsonb。jsonb比json更为高效,因为它能够在查询过程中使用索引和更好的压缩,因此jsonb也是我们更倾向于使用的类型。 本文将详细讲解如何使用PostgreSQL中的jsonb属性,包括添加、更新、删除jsonb属性…

    C 2023年5月23日
    00
  • C++实现银行排队系统

    C++实现银行排队系统 介绍 银行排队系统是一种经典的模拟系统。该系统可以模拟银行中客户的流动、排队、服务等过程。通过模拟,可以帮助银行评估服务能力,从而提高工作效率。本文将介绍如何使用C++实现银行排队系统。 系统设计 队列的实现 队列是银行排队系统的核心数据结构。在C++中,可以使用STL中的队列容器来实现队列。以下是如何定义一个整型队列: “`c++…

    C 2023年5月23日
    00
  • 基于javascript实现按圆形排列DIV元素(二)

    基于JavaScript实现按圆形排列DIV元素的完整攻略如下: 步骤1:构建HTML结构 首先,我们需要构建一个HTML页面,并在其中添加一个父级div元素和一些子级的div元素。父级div元素用于容纳所有子级div元素,并设置其宽度和高度为固定值,例如600px。子级div元素用于显示实际内容,我们只需要设置它们的宽度和高度即可。 <div id=…

    C 2023年5月22日
    00
  • C语言小程序 杨辉三角示例代码

    下面我来为您详细讲解“C语言小程序 杨辉三角示例代码”的攻略。 什么是杨辉三角 杨辉三角,又称帕斯卡三角形,是二项式系数在三角形中的一种几何排列。它是中国古代数学的杰出研究成果之一,杨辉是唐朝末年、宋朝初年的一位著名数学家。 杨辉三角的规律是:每个数等于它上方两数之和。它的形状如下图所示: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 …

    C 2023年5月23日
    00
  • SpringBoot配置GlobalExceptionHandler全局异常处理器案例

    下面是 SpringBoot 配置 GlobalExceptionHandler 全局异常处理器的完整攻略。 什么是 GlobalExceptionHandler? GlobalExceptionHandler 是 SpringBoot 框架提供的一种全局异常处理机制,它可以帮助我们捕获项目中出现的异常并返回友好的提示信息,从而提高用户体验。 如何配置 Gl…

    C 2023年5月23日
    00
  • NBA2KOL海耶斯投篮包怎么样 C级球员投篮包介绍

    NBA2KOL海耶斯投篮包怎么样 在NBA2KOL中,海耶斯投篮包是一种帮助球员训练投篮技巧的道具,使用之后可以提高C级球员的投篮能力。本篇攻略将介绍海耶斯投篮包的使用方法和效果,同时帮助球员更好地理解C级球员投篮包。 海耶斯投篮包使用方法 在游戏中,将鼠标移到主菜单的“训练”选项上,选择“篮球基础训练”进入训练模式。之后,在球场的右侧将看到海耶斯投篮包的图…

    C 2023年5月23日
    00
  • C++实现学生住宿管理系统

    C++实现学生住宿管理系统攻略 系统介绍 学生住宿管理系统主要功能是管理学生住宿信息,包括学生的基本信息和住宿信息,如宿舍楼、宿舍号、床位号等。该系统可以实现学生住宿信息的增删改查等基本操作,方便学生和管理员进行管理。 系统设计 数据库设计 首先,我们需要设计一个数据库,用来存储学生信息和住宿信息。可以使用MySQL或SQLite等关系型数据库,也可以使用文…

    C 2023年5月23日
    00
  • Python常见读写文件操作实例总结【文本、json、csv、pdf等】

    Python常见读写文件操作实例总结 本文将介绍在Python中针对常见文件类型的读写操作,包括文本、JSON、CSV以及PDF等格式。 文本文件读写 读取文本文件 读取文本文件很简单,可以使用Python内置的open()函数来打开文件,然后读取文件的内容。open()函数接收两个参数,第一个参数是要读取的文件的路径,第二个参数是打开文件的模式,我们这里使…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部