深拷贝和浅拷贝的区别及实现方法

article/2025/9/17 3:52:02

文章目录

  • 一、引言
  • 二、浅拷贝
    • 1.Object.assign()
    • 2.concat()
    • 3.扩展运算符
  • 三、深拷贝
    • 1. 利用json数据和json字符串之间的转换
    • 2.$.extend()
    • 3. 递归

查阅多篇文章后,自己归纳总结对深拷贝和浅拷贝的理解,不足之处,还望多多指导

一、引言


基本数据类型 的数据赋值后,更改赋值后的变量,两者互不影响;

let a = 100;
let b = a;
a = 200;console.log(a); // 200
console.log(b); // 100

引用数据类型 的数据赋值后,将存放在栈内存中的地址赋值给接收的变量,更改赋值后的变量,会影响到原来的数据

// 复杂数据类型:Array、Object
let obj1 = {name:"小李",age:18}let obj2 = obj1
obj1.age = 25;console.log( obj1 ); 	// {name:"小李", age:25}
console.log( obj2 ); 	// {name:"小李", age:25}

针对以上问题 引出了本文的解决方案 深拷贝浅拷贝

二、浅拷贝


定义:
创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。
如果属性是基本类型,拷贝的就是基本类型的值。
如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

缺陷: 浅拷贝只能实现一层的拷贝,无法进行深层次的拷贝

实现方法

1.Object.assign()

ES6中拷贝对象的方法,接受的第一个参数是拷贝的目标,剩下的参数是拷贝的源对象(可以是多个)

语法:Object.assign(target, ...sources)

举个栗子:

let obj1 = {name: "小李",age: 18
}
// Object.assign()  会返回一个新对象 // 这种写法和下面写法实现效果一样
// let obj2 = Object.assign({}, obj1)let obj2 = {}
Object.assign(obj2, obj1)
obj1.name = '小张';
obj1.age = '25';console.log(obj1); // {name:"小张", age:25}
console.log(obj2); // {name:"小李", age:18}

2.concat()

语法:concat() 合并两个或多个数组,返回一个新数组。原数组不变

举个栗子:

let arr = [1,2,3,4];
let newArr = arr.concat()
arr.push(5);console.log(arr);		// [1,2,3,4,5]
console.log(newArr );	// [1,2,3,4]

3.扩展运算符

如果对象中的属性都是基本数据类型的话,使用扩展运算符更加方便

举个栗子:

let obj1 = {name: "小李",age: 18
}
let obj2 = {...obj1}obj1.name = '小张';
obj1.age = '25';
console.log(obj1, obj2);let arr = [1, 2, 3]
let newArr = [...arr]
arr[0] = 999
console.log(arr, newArr)

运行结果:
在这里插入图片描述

三、深拷贝


不管原数据中值是什么类型的数据,拷贝后的新数据跟原数据是相互独立,没有关联的

实现方法

1. 利用json数据和json字符串之间的转换

JSON.stringify() 将对象转换成JSON字符串

JSON.parse() 反序列化将JSON字符串变成一个新的对象

对于日常的开发需求(对象和数组),使用这种方法是最简单和快捷的

缺点: 无法实现对对象中 方法 的拷贝,会显示为undefined

let obj1 = {name: "小李",age: 18,father: {age: 40},fn: function () {return 123}
}
let temp = JSON.stringify(obj1)
let obj2 = JSON.parse(temp)obj1.father.age = 50;console.log(obj1); 		// {name:"小李", age:18, father:{age:50},fn()}
console.log(obj2); 		// {name:"小张", age:25, father:{age:40}}
console.log(obj2.fn) 	// underfind

2.$.extend()

直通车: https://www.jquery123.com/jQuery.extend/.

语法: jQuery.extend([deep], target, object1, [objectN])

deep默认为false

举个栗子:

// 注意要引入jQuery的CDN才能使用该方法
let obj1 = {name: "小李",age: 18,father: {age: 40},fn: function () {return 123}
}let obj2 = $.extend(true, {}, obj1)obj1.father.age = 50;console.log(obj1,obj2);

运行结果:
在这里插入图片描述

3. 递归

function deepClone(obj) {// 定义一个对象,用来确定当前的参数是数组还是对象let objClone = Array.isArray(obj) ? [] : {};// 判断obj是否存在,且类型是对象。(typeof [] 也是 object)if (obj && typeof obj === "object") {// 遍历参数的键for (key in obj) {// hasOwnProperty() 方法不会检测对象的原型链,只会检测当前对象本身存在该属性时才返回 true,常与for...in使用// 判断对象是否存在该属性if (obj.hasOwnProperty(key)) {// 值是对象就递归if (obj[key] && typeof obj[key] === "object") {objClone[key] = deepClone(obj[key]);} else {// 基本数据类型  直接赋值objClone[key] = obj[key];}}}}return objClone;
}
let a = {name: "小李",age: 18,father: {name: "大李",},fn: function () {return 123}
}
let b = deepClone(a)
a.father.name = "小李他爸"console.log(a, b);

运行结果:
在这里插入图片描述


http://chatgpt.dhexx.cn/article/HreNVhbL.shtml

相关文章

深拷贝与浅拷贝的区别

深拷贝与浅拷贝是针对对象属性为对象的,因为基本数据类型在进行赋值操作时(也就是深拷贝(值拷贝)),是直接将值赋给了新的变量,也就是该变量是原变量的一个副本,这时,你修…

深拷贝和浅拷贝的区别是什么?

深拷贝和浅拷贝的区别是什么? 1、浅拷贝 (1)、定义 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主"对象进行拷贝,但不会复制主对象里面的对象。"里面的对象”会在…

深拷贝和浅拷贝常见的实现方式

浅拷贝的实现方式 1. Object.assign()方法 assign()方法是把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是他的拷贝方式不是固定的,看下面的代码演示: let obj {username: kobe}; let obj2 Object.assign({},o…

什么是深拷贝和浅拷贝?以及怎么实现深拷贝和浅拷贝?

拷贝浅是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了这个地址,就会影响到…

Java的深拷贝与浅拷贝的区别

1.二者的区别 浅拷贝:在拷贝一个对象时,对对象的基本数据类型的成员变量进行拷贝,但对引用类型的成员变量只进行引用的传递,并没有创建一个新的对象,当对引用类型的内容修改会影响被拷贝的对象。 深拷贝:在…

深拷贝和浅拷贝的区别(必须掌握)

前言: 在面试中,你必须要知道的一个知识点,那就是浅拷贝和深拷贝,那么就必须知道基本数据类型和引用类型,其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。 网片来自网络(侵删) …

C++的浅拷贝与深拷贝

目录 前言 一、区别 二、浅拷贝 1.简单描述 2.代码实例 三.深拷贝 1.简单描述 2.代码实例 四.完整代码 五.运行结果 总结 前言 C中有两种拷贝:深拷贝和浅拷贝 要是想要运用好拷贝函数就必须清楚深拷贝与浅拷贝的区别 一、区别 1 在未定义拷贝构造函数…

拷贝构造(深拷贝、浅拷贝)

一、概念介绍 拷贝构造:拷贝构造函数,又称构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构造及初始化。 其唯一的形参必须是引用,但并不限制为const,一般普遍的会加上c…

C++——深拷贝和浅拷贝

1.浅拷贝与深拷贝的区别 浅拷贝(默认拷贝函数):将原对象或原数组的引用直接赋给新对象,新数组,新对象/新数组只是原对象的一个引用。 深拷贝:创建一个新的对象和数组,将原对象的各项属性的“值”…

深拷贝和浅拷贝的区别和与原理

一、基本类型和引用类型 string,number,boolean,null,undefined,symbolFunction,Array,Object 基本类型是按值访问的,引用类型是按引用访问 基本类型和引用类型也有人叫原始类型和对象类型,拥有方法的类型和不能拥有方法的类型,可变类型和不…

浅拷贝、深拷贝

深拷贝和浅拷贝 这两个概念是在项目中比较常见的,在很多时候,都会遇到拷贝的问题,我们总是需要将一个对象赋值到另一个对象上,但可能会在改变新赋值对象的时候,忽略掉我是否之后还需要用到原来的对象,那么就…

深拷贝和浅拷贝(copy和deepcopy)详解

深拷贝和浅拷贝(copy和deepcopy)详解 详细解释存储方式列表的增删改列表修改已有值列表新增一个值列表整体重新赋值 copy与deepcopy的区别不可变类型可变类型 浅拷贝指的是创建一个新对象,其中包含原始对象的引用(指针&#xff09…

浅拷贝和深拷贝的区别?

创建Java对象的方式包括new、反射、反序列化、拷贝,那么什么是拷贝呢?浅拷贝和深拷贝又有什么区别呢? 什么是拷贝 拷贝就是为了复用原对象的部分或全部数据,在原对象的基础上通过复制的方式创建一个新的对象。 Object类中有nati…

深拷贝和浅拷贝的区别

首先,明确一点深拷贝和浅拷贝是针对对象属性为对象的,因为基本数据类型在进行赋值操作时(也就是拷贝)是直接将值赋给了新的变量,也就是该变量是原变量的一个副本,这个时候你修改两者中的任何一个的值都不会…

浅拷贝与深拷贝的区别

浅拷贝与深拷贝 一、数据类型 数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。 基本数据类型的特点:直接存储在栈(stack)中的数据 引用数据类型的特点:存储的是该对象在栈中引用,真实的…

堆、栈和队列

1. 堆 堆是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。堆是指程序运行时申请的动态内存,而栈只是指一种使用堆的方法(即先进后出)。 2. 栈(stack&…

堆、栈和队列的区别

目录 数据结构中的堆、栈和队列 内存申请中的堆和栈 一个C/C程序占用的内存如下: 申请内存后的响应 申请大小的限制 申请效率的比较 堆和栈中的存储内容 数据结构中的堆、栈和队列 堆:堆是一种经过排序的树形数据结构,每个结点都有…

栈和队列

文章目录 栈栈操作队列队列操作双端队列双端队列操作 栈 栈(stack),有些地方称为堆栈,是一种容器,可存入数据元素、访问元素、删除元素,它的特点在于只能允许在容器的一端(称为栈顶端指标&…

栈和队列简介

栈和队列简介 栈和队列是两种常用的数据结构,它们的数据是按线性结构存储的,因此,栈和队列也属于线性表。 栈和队列的数据可以存储在一个顺序表里,也可以存储在一个链表里,只要满足线性存储结构就行。只对数据的线性…

栈和队列基本操作

栈和队列 一、栈栈是什么栈的实现栈的基本操作栈类型的定义初始化栈检查栈是否为满入栈出栈获取栈顶元素检测栈是否为空测试函数 完整代码Stack.hStack.cmain.c 二、队列队列是什么队列的实现队列类型的定义申请一个节点初始化队列队尾入队列队头出队列获取队列头部元素获取队列…