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

article/2025/9/16 21:04:06

前言:

在面试中,你必须要知道的一个知识点,那就是浅拷贝和深拷贝,那么就必须知道基本数据类型和引用类型,其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。

网片来自网络(侵删)
在这里插入图片描述

重点:你需要记住一句话:值类型传递的是值,引用类型传递的是地址

基本数据类型

这里就不做过多介绍了,基本数据类型值放在栈区,可直接访问与修改,且相互之间不会影响

引用类型

引用类型地址放在栈区,值放在堆区,所以当你进行赋值操作,其实赋值的是地址,所以二者之间是有关系的:

var obj1={name:'mengyun',age:18
};
var obj2 = obj1;
obj2.name = 'meimei';
console.log(obj1);//{name:'meimei',age:18}
console.log(obj2);//{name:'meimei',age:18}

可见是有联系的,而且曾经我一度以为赋值操作就是浅拷贝,其实不是的,还是太年轻~

下面看一个例子:

var obj1 = {name: 'mengyun',age: 18,hobby:{ play: [ 'footboll' ], read: 'book' },eat: ['苹果', '香蕉', '菠萝']
};var obj2 = obj1;function shallowCopy(target) {var result;if (Object.prototype.toString.call(target).slice(8, -1) === 'Object'){result={}}else if(Object.prototype.toString.call(target).slice(8, -1) === 'Array'){result=[]}for (var prop in target) {if (target.hasOwnProperty(prop)) {result[prop] = target[prop];}}return result;
}
var obj3 = shallowCopy(obj1);
obj2.name = "meimei";
obj3.age = "20";
obj2.hobby.play = ["games"];
obj3.hobby.read= ["news"];
obj3.eat = ['哈密瓜']; // 修改一层引用类型
console.log(obj1);
console.log(obj2);
console.log(obj3);

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

因为浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。所以就会出现改变浅拷贝得到的 obj3 中的引用类型时,会使原始数据得到改变。而且浅拷贝可以修改第一层的引用类型

浅拷贝:

拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象,直接复制,或者说,就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用

实现浅拷贝的方法:

  1. 手写一个浅拷贝
function shallowCopy(target) {var result;if (Object.prototype.toString.call(target).slice(8, -1) === 'Object'){result={}}else if(Object.prototype.toString.call(target).slice(8, -1) === 'Array'){result=[]}for (var prop in target) {if (target.hasOwnProperty(prop)) {result[prop] = target[prop];}}return result;
}
  1. Object.assign()
var obj1 = {
name: 'mengyun',age: 18,hobby: { play: ['footboll'], read: 'book' },eat: ['苹果', '香蕉', '菠萝'],
};var obj2 = obj1;var obj3 = Object.assign({}, obj1);
obj2.name = "meimei";
obj3.age = "20";
obj2.hobby.play = ["games"];
obj3.hobby.read = ["news"];
obj3.eat = ['哈密瓜']; // 修改一层引用类型
console.log(obj1);
console.log(obj2);
console.log(obj3);

结果和上面一样

  1. 数组的浅拷贝
    展开运算符
var arr1=[1,2,3];
var arr2 = arr1;
arr2[1]='666';
console.log(arr1);//[1, "666", 3]
console.log(arr2);//[1, "666", 3]var arr3 = [5,6,7];
var arr4 = [...arr3];
arr4[1]='666';
console.log(arr3);//[5,6,7]
console.log(arr4);//[5, "666", 7]

concat():

const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

深拷贝:

把一个对象中所有的属性或者方法,一个一个的找到,并且在另一个对象中开辟相应的空间,一个一个的存储到另一个对象中

实现深拷贝的方法:

  1. JSON.parse(JSON.stringify())
let obj1 = {a:3,b:4
}let str = JSON.stringify(obj1);
let obj2 = JSON.parse(str);
obj2.a = 5;
console.log(obj1);  //{a: 3, b: 4}
console.log(obj2);  //{a: 5, b: 4}
  1. 手写一个深拷贝(递归)
    法1:
function deepClone(target) {var result;if (Object.prototype.toString.call(target).slice(8, -1) === 'Object') {result = {}} else if (Object.prototype.toString.call(target).slice(8, -1) === 'Array') {result = []}else{return target}for (var prop in target) {if (target.hasOwnProperty(prop)) {result[prop] = deepClone(target[prop]);}}return result;
}

法2:

function deepClone(target) {if(typeof target !=='object' || target==null){//target是null,或者不是数组、对象,直接返回return target}let result;//初始化结果if(target instanceof Array){result = []}else{result = {}}for (var prop in target) {if(target.hasOwnProperty(prop)){//保证key不是原型上的属性result[prop] = deepClone(target[prop]);}}return result;
}

测试案例:

var obj1 = {name: 'mengyun',age: 18,hobby: { play: ['footboll'], read: 'book' },eat: ['苹果', '香蕉', '菠萝'],
};var obj2 = obj1;var obj3 = deepClone(obj1);
obj2.name = "meimei";
obj3.age = "20";
obj2.hobby.play = ["games"];
obj3.hobby.read = ["news"];
obj3.eat = ['哈密瓜']; // 修改一层引用类型
console.log(obj1);
console.log(obj2);
console.log(obj3);

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

最后:

记住这张图
在这里插入图片描述
(图片侵删)

区别:

浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制


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

相关文章

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 二、队列队列是什么队列的实现队列类型的定义申请一个节点初始化队列队尾入队列队头出队列获取队列头部元素获取队列…

C#队列和栈的使用

一、队列 队列是其元素以先进先出&#xff08;Firstin,Firstout,FIFO&#xff09;的方式来处理的集合。先放入队列中的元素会先读取。队列使用System.Collections.Generic命名空间中的泛型类Queue<T>实现。 队列的成员 Count&#xff1a;Count属性返回队列中元素个数。…

栈和队列经典面试题

目录 1、括号匹配问题 2、用队列实现栈 3、用栈实现队列 4、设计循环队列 1、括号匹配问题 链接直达&#xff1a; 有效的括号 题目&#xff1a; 思路&#xff1a; 做题前&#xff0c;得先明确解题方案是啥&#xff0c;此题用栈的思想去解决是较为方便的&#xff0c;栈明确指…

栈stack和队列

栈和队列 一 栈和队列二 栈三.队列 一 栈和队列 栈和队列是两种重要的线性结构。从数据结构来看&#xff0c;栈和队列也是线性表&#xff0c;其特殊性在于栈和队列的基本操作是线性表操作的子集&#xff08;也具有顺序结构和链式结构&#xff09;&#xff0c;它们是操作受限的…

链表,队列和栈的区别

链表&#xff0c;队列和栈都是数据结构的一种。Sartaj Sahni 在他的《数据结构、算法与应用》一书中称&#xff1a;“数据结构是数据对象&#xff0c;以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出。”他将数据对象&#x…

栈与队列的定义与区别

1、栈 首先&#xff0c;普通的线性表实现是有两个端口可以访问的&#xff0c;但是如果作为栈就要封闭一端&#xff0c;只能访问另一端。这当然不是自讨苦吃&#xff0c;栈是一种抽象数据结构&#xff0c;是对现实世界对象的模拟。比如&#xff0c;自助餐厅中的一叠盘子&#x…

java 队列和栈的区别

栈和队列的区别 &#xff08;1&#xff09;数据插入删除 栈是一种特殊的线性表&#xff0c;他只能在一段进行插入和删除操作&#xff0c;就好像是一个井一样。进行数据插入和删除就类似于井口&#xff0c;称为栈定。而井也是有底部的&#xff0c;栈无法进行插入删除操作的这一…