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日

相关文章

  • C语言字符串快速压缩算法代码

    C语言字符串快速压缩算法代码 什么是字符串快速压缩算法 字符串压缩是一种将文本数据编码为较短二进制串的技术,其可以对一定范围内的部分文本数据进行无损压缩,使得压缩后的数据占用更小的存储空间,也方便网络传输和存储。 字符串快速压缩算法是一种快速编码和高效解码的无损算法。该算法的主要思想是通过统计原始数据中出现的字符及其出现的频率,选用最出现频率的字符在新的编码…

    C 2023年5月22日
    00
  • C和C++的区别详解

    C和C++的区别详解 C和C++是两种非常常见的编程语言,在很多领域都有广泛的应用。虽然在某些方面它们很相似,但在许多方面它们也存在很大的差异。下面我们将详细说明C和C++之间的区别。 1. 语言的起源和发展历史 C语言是由Dennis Ritchie在20世纪70年代初创造的,最初是为了在Unix操作系统上编写系统级应用程序而设计的。C++语言则是由Bja…

    C 2023年5月22日
    00
  • 酷派大神F1怎么开启C键?

    酷派大神F1开启C键攻略 如果您是酷派大神F1手机的用户,可能会遇到需要使用C键的情况。但是,许多人并不知道该如何在酷派大神F1手机上开启C键。本篇文章将讲解如何开启C键,并提供示例以帮助您更好地理解和操作。 第一步:打开设置 首先,您需要打开酷派大神F1手机的设置菜单。您可以在移动设备屏幕上找到应用菜单,从中打开设置选项。 第二步:进入系统设置 在设置菜单…

    C 2023年5月23日
    00
  • C语言实现学生成绩等级划分的方法实例

    C语言实现学生成绩等级划分的方法实例 概述 本文将介绍如何使用C语言实现学生成绩等级划分的方法,并提供两个示例说明。 学生成绩等级划分是一个常见的应用场景,可以帮助老师和学生更加清楚地了解学生成绩的情况,方便对学生进行教学和管理。 在本文中,我们将介绍如何使用C语言实现一个学生成绩等级划分程序,以及如何进行测试。 步骤 1.明确需求 我们需要设计一个C语言程…

    C 2023年5月23日
    00
  • CCleaner Pro怎么激活?CCleaner专业版注册破解激活教程(附下载)

    CCleaner Pro激活攻略 1. 下载CCleaner专业版安装文件 首先,你需要下载CCleaner专业版安装文件。你可以在官方网站上下载安装文件,也可以在其他下载站点上下载。注意,要下载专业版,而不是免费版。 下载完成后,双击安装文件并按照提示进行安装。 2. 获取CCleaner专业版注册码 在你安装CCleaner专业版后,你将需要注册码来激活…

    C 2023年5月23日
    00
  • C语言超详细讲解猜数字游戏的实现

    C语言超详细讲解猜数字游戏的实现 简介 本攻略将会详细讲解如何使用C语言实现猜数字游戏。猜数字游戏是非常基础的小游戏,可以用来帮助初学者掌握一些基本的编程概念和语法。 猜数字游戏的规则 在该游戏中,程序会随机生成一个1-100之间的整数,玩家需要在有限次数内猜中这个数字。每次猜测后,程序会提示玩家输入的数字与随机数字之间的大小关系,直到玩家猜中或猜测的次数用…

    C 2023年5月22日
    00
  • C语言中栈的两种实现方法详解

    C语言中栈的两种实现方法详解 栈,即先进后出(LIFO)的数据结构。在C语言中,栈是一个重要的概念,可以用于实现各种算法和数据结构。 本文主要介绍C语言中栈的两种实现方法。 方法一:基于数组实现栈 基于数组实现栈是一种简单的方法。我们可以定义一个数组作为栈的存储空间,并且定义栈顶指针(top)来指示栈顶元素的位置。 下面是一个简单的示例代码: #includ…

    C 2023年5月23日
    00
  • C++ Boost log日志库超详细讲解

    C++ Boost log日志库超详细讲解 什么是C++ Boost log日志库? C++ Boost log是一个高度灵活和可定制的C++日志库,它提供了一系列便利的接口和功能,帮助我们实现日志的收集、保存、查询和分析等操作。同时,它还提供了多种日志输出格式和输出目标,例如标准输出、文件、syslog等。 安装C++ Boost log日志库 在使用C+…

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