首页 > 编程语言 >JavaScript 中对象的浅拷贝(Shallow Copy)和深拷贝(Deep Copy)!!

JavaScript 中对象的浅拷贝(Shallow Copy)和深拷贝(Deep Copy)!!

时间:2024-03-22 11:02:02浏览次数:28  
标签:obj 对象 JavaScript 引用 拷贝 Copy 属性

在 JavaScript 中,对象的拷贝可以分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。理解这两者的区别是非常重要的,因为它们影响着拷贝后的对象与原始对象之间的关系。

  1. 浅拷贝(Shallow Copy):

浅拷贝只会拷贝对象的第一层属性。如果对象的属性是基本数据类型(例如,字符串,数字,布尔值等),那么拷贝的就是基本数据类型的值。但如果属性是引用数据类型(例如,对象,数组等),拷贝的就是这个属性在内存中的地址,而不是真正的内容。这就意味着,如果修改了这个拷贝后的对象中的引用类型属性,那么原始对象也会被改变。

JavaScript 中实现浅拷贝的方法有很多种,例如使用 Object.assign() 或者展开运算符 ...

const obj = { a: 1, b: 2, c: { d: 3 } };
const shallowCopy = { ...obj };
shallowCopy.c.d = 4;

console.log(obj); // { a: 1, b: 2, c: { d: 4 } }
console.log(shallowCopy); // { a: 1, b: 2, c: { d: 4 } }

你可以看到,虽然我们修改了 shallowCopy 对象的 c.d 属性,但原始对象 obj 的相应属性也被改变了,这就是浅拷贝的特性。

  1. 深拷贝(Deep Copy):

深拷贝会拷贝对象的所有层级,包括它的所有子对象和子数组等。这意味着,对于对象的任何属性,无论是基本数据类型还是引用数据类型,都会被完全复制一份,形成一份全新的对象。这样,无论怎么修改新对象,都不会影响到原始对象。

在 JavaScript 中,可以通过一些方法实现深拷贝,例如 JSON.parse(JSON.stringify(object))(注意,这个方法有局限性,无法处理函数、undefined、循环引用等)。此外,还有一些库,如 lodash 的 _.cloneDeep() 方法,也可以实现深拷贝。

const obj = { a: 1, b: 2, c: { d: 3 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.c.d = 4;

console.log(obj); // { a: 1, b: 2, c: { d: 3 } }
console.log(deepCopy); // { a: 1, b: 2, c: { d: 4 } }

在这个例子中,你可以看到,虽然我们修改了 deepCopy 对象的 c.d 属性,但原始对象 obj 的相应属性并未被改变,这就是深拷贝的特性。

两者的区别

浅拷贝与深拷贝之间的区别主要体现在对对象内部引用类型的处理方式上,以及拷贝后新对象与原始对象之间的独立性。以下是两者之间的详细区别:

浅拷贝(Shallow Copy)

  1. 引用类型共享:浅拷贝仅复制对象的顶层属性。如果对象的属性值是基本类型(如数字、字符串、布尔值等),则直接复制该值。但如果属性值是引用类型(如对象、数组、函数等),则复制的是内存地址的引用,而不是实际的对象。因此,原始对象和拷贝后的对象会共享同一个引用类型的实例。

  2. 修改影响原始对象:由于引用类型的共享,如果对拷贝后的对象中的引用类型属性进行修改,这些修改也会反映到原始对象中。这是因为两者都指向同一个内存地址。

  3. 性能开销较小:浅拷贝通常比深拷贝更快,因为它不需要递归地复制对象的所有层级。

  4. 实现方式:在 JavaScript 中,可以使用 Object.assign() 方法、展开运算符(...)或数组的 slice()concat() 方法等来实现浅拷贝。

深拷贝(Deep Copy)

  1. 完全独立:深拷贝会递归地复制对象的所有层级,包括所有的子对象和子数组。这意味着拷贝后的对象是一个完全独立的实例,与原始对象没有任何关联。

  2. 修改不影响原始对象:由于深拷贝创建了对象的完整副本,包括所有引用类型的属性,因此对拷贝后的对象进行的任何修改都不会影响原始对象。

  3. 性能开销较大:深拷贝通常比浅拷贝更慢且更消耗内存,因为它需要递归地复制对象的所有层级和属性。

  4. 实现方式:在 JavaScript 中,可以使用 JSON.parse(JSON.stringify(object))(有局限性,无法处理函数、undefined、循环引用等)或第三方库(如 lodash 的 _.cloneDeep() 方法)来实现深拷贝。

  5. 处理循环引用:深拷贝的一个挑战是处理对象之间的循环引用。如果对象之间存在循环引用,简单的递归复制可能会导致无限循环。因此,实现深拷贝的库通常需要具备检测和处理循环引用的能力。

综上所述,浅拷贝和深拷贝的主要区别在于它们对引用类型属性的处理方式以及拷贝后新对象与原始对象之间的独立性。选择使用哪种拷贝方式取决于具体的应用场景和需求。

标签:obj,对象,JavaScript,引用,拷贝,Copy,属性
From: https://blog.csdn.net/qq_43536788/article/details/136841266

相关文章

  • 网页禁止copy(复制)的解决方案
    当我们浏览些网页时回遇到一些网页是不能copy的,这样的体验就一点都友好。接下来就介绍一下如何解除这种限制!首先我们先打开调试窗口---->Elements---->EventListeners---->找到copy事件,把他干掉就......
  • 前端基础之JavaScriptDOM和BOM
    一、JavaScript的组成JavaScript的实现包括以下3个部分:ECMAScript(核心)描述了JS的语法和基本对象文档对象模型(DOM)处理网页内容的方法和接口浏览器对象模型(BOM)与浏览器交互的方法和接口核心(Core):核心部分包括语言的基本语法、数据类型、控制结构等。这些......
  • PGSQL COPY 命令的使用
    ddd根据大佬的测试 https://developer.aliyun.com/ask/54534,copy命令的效率是很高的。但copy命令只能操作本机的文件,所以浏览器上传的文件需要通过共享文件夹上传部署PGSQL服务器(测试IP为:192.168.1.11)中。//Uploadentirefile   UploadWholeFile.ashx......
  • JavaScript初识及基本语法详解
    JavaScript是一种轻量级的解释型或即时编译型的编程语言。它最初被设计为在浏览器中用于与网页进行交互,但随着时间的推移,它已经成为了后端开发、游戏开发、桌面应用开发等多个领域的重要工具。1.JavaScript初识1.1历史与用途历史:由BrendanEich在1995年开发,最初......
  • 07-JavaScript对象
     <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>JS-对象-Array</title></head><body><script>//第一种方法,定义数组vararr=newArray(1,2,3,4);......
  • 前端基础之JavaScript数组
    数组一、什么是数组数组类似于python里面的列表[]在编程中,数组(Array)是一种数据结构,用于存储相同类型的多个元素。这些元素按照顺序排列,并通过索引(通常是非负整数)来访问。数组可以包含各种数据类型,例如整数、浮点数、字符串,甚至其他数组。在许多编程语言中,数组的大小是固定......
  • 前端基础之JavaScript运算符
    一、什么是运算符运算符,顾名思义就是在运算中的符号,例如加法中的”+“就是一个运算符。严谨来说,运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。二、运算符的分类JavaScript中的运算符可以分为多种类型,包括算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算......
  • 前端基础之JavaScript流程控制
    一、if判断在JavaScript中,if语句是一种常见的条件语句,用于根据条件执行不同的代码块。除了基本的if语句外,还有if...else、if...elseif...else等变体,用于处理多个条件的情况。1.if语句if语句用于在条件为真时执行特定的代码块。语法:if(condition){//当条件......
  • 前端基础之JavaScript对象
    一、什么是对象现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,一个数据库、一张网页、一个与远程服务器的连接也可以是“对象”。在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字......
  • 前端基础之JavaScript函数
    一、什么是函数在JavaScript中,函数是一种可重复使用的代码块,用于执行特定任务或计算。函数可以接受参数,执行特定的操作,并返回一个值。二、函数的声明函数可以通过函数声明、函数表达式或箭头函数来定义。函数声明:functionfunctionName(parameters){//函数体......