
- 要 求
- 复制对象空间和资源
- 特 点
- 源对象与拷贝对象互相独立
- 有关术语
- 拷贝构造函数
- 中文名
- 深拷贝
- 学 科
- 软件工程
- 外文名
- deep copy
-
深拷贝
2019-02-11 15:28:201. JS 中拷贝对象分为浅拷贝和深拷贝 浅拷贝 : 拷贝引用 深拷贝 : 拷贝里面的数据成新的对象 2. 常规做法 递归 , 简单实现方式如下: var a = {name: "xiaoming"} var b = JSON.parse(JSON....1. JS 中拷贝对象分为浅拷贝和深拷贝
浅拷贝 : 拷贝引用
深拷贝 : 拷贝里面的数据成新的对象
2. 常规做法 递归 , 简单实现方式如下:
var a = {name: "xiaoming"} var b = JSON.parse(JSON.stringify(a)) // b 就是对 a 的一个深拷贝
当对象中包含
undefined
、函数
以及symbol
值的时候,在JSON.stringify()
序列化过程中会被忽略,所以需要避免在包含上述值的源对象中采用这种拷贝方式 -
javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法
2017-02-08 19:12:05javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法前言在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示: 如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并...javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法
前言
在js中,数组和对象的复制如果使用
=
号来进行复制,那只是浅拷贝。如下图演示:
如上,arr
的修改,会影响arr2
的值,这显然在绝大多数情况下,并不是我们所需要的结果。
因此,数组以及对象的深拷贝就是javascript
的一个基本功了。评论中有很多人说我误导大家。说这些都是浅拷贝。我不做过深的阐述,本文中涉及到的都是比较浅显的内容。诸位请根据自己的需要以及情况自行判断和理解。
数组的深拷贝
条条大道通罗马,实现数组的深拷贝,是有好几种方法的。举例如下:
for 循环实现数组的深拷贝
for循环是非常好用的。如果不知道高级方法,通过for循环能够完成我们大多数的需求。
var arr = [1,2,3,4,5] var arr2 = copyArr(arr) function copyArr(arr) { let res = [] for (let i = 0; i < arr.length; i++) { res.push(arr[i]) } return res }
如上,通过对数组的for循环,即可实现对数组的深拷贝了。
slice 方法实现数组的深拷贝
这个代码实现非常简单。原理也比较好理解,他是将原数组中抽离部分出来形成一个新数组。我们只要设置为抽离全部,即可完成数组的深拷贝。代码如下:
var arr = [1,2,3,4,5] var arr2 = arr.slice(0) arr[2] = 5 console.log(arr) console.log(arr2)
运行结果如下:
更多slice
内容请访问 w3school JavaScript slice 方法concat 方法实现数组的深拷贝
这个代码也非常简单,原理更加粗暴。它是用于连接多个数组组成一个新的数组的方法。那么,我们只要连接它自己,即可完成数组的深拷贝。代码如下:
var arr = [1,2,3,4,5] var arr2 = arr.concat() arr[2] = 5 console.log(arr) console.log(arr2)
运行结果如下:
更多concat
内容请访问 w3school JavaScript concat 方法2017年10月31日补充:ES6扩展运算符实现数组的深拷贝
OK,以上之前讲的方法全部过时了,用下面的方法实现数组的深拷贝是最简单的。
var arr = [1,2,3,4,5] var [ ...arr2 ] = arr arr[2] = 5 console.log(arr) console.log(arr2)
运行结果如下:
对象的深拷贝
对象的深拷贝相比数组也没有困难许多,列举两个方法。
万能的for循环实现对象的深拷贝
在很多时候,for循环能够解决大问题。
var obj = { name: 'FungLeo', sex: 'man', old: '18' } var obj2 = copyObj(obj) function copyObj(obj) { let res = {} for (var key in obj) { res[key] = obj[key] } return res }
转换成json再转换成对象实现对象的深拷贝
上面的代码实在是比较长,所以,用一个更暴力的方法吧!代码如下:
var obj = { name: 'FungLeo', sex: 'man', old: '18' } var obj2 = JSON.parse(JSON.stringify(obj))
这个原理没什么好解释的,实在是够简单粗暴的啦!
2017年10月31日补充: 扩展运算符实现对象的深拷贝
var obj = { name: 'FungLeo', sex: 'man', old: '18' } var { ...obj2 } = obj obj.old = '22' console.log(obj) console.log(obj2)
运行结果如下:
小结
数组和对象的深拷贝是js中最常见的应用。理解各种方法是必须的。希望对大家有所帮助。
本文中并没有对异常进行处理,主要在讲原理。更多的数组以及对象的操作方法,可以参考lodash
的源码,查看它的源码可以让你的js基础变得非常牢固。我也在学习中。2017年10月31日补充,使用es6提供的扩展运算符的方法实现深拷贝,简单,高效。并且,对象的深拷贝不会像使用
JSON
方法深拷贝一样,丢失函数等信息,只能用来深拷贝JSON
数据格式的对象。推荐大家使用。补充一个数组去重的方法
function dedupe(array) { return [...new Set(array)] } var arr = [1,2,2,3,3,4,4,5,5] console.log(dedupe(arr))
运行结果如下:
2021年03月29日 补充
这里说的深拷贝,都是指一维的数组和对象的深拷贝。鉴于评论中多人指出,这些是浅拷贝,我本来不想回应,但是提出这个观点的人很多,因此我在这边回应一下。
浅拷贝的概念不重复了,上文中已经说明。文章中的多种方法,均不是浅拷贝,只是是否支持多维数据而已。而在绝大多数场景下,文中的方法是适用的。
想要简便的支持多维数据的深拷贝,可以直接适用 JSON 方式。或适用 lodash 工具实现。
版权申明:本文由FungLeo原创,允许转载,但转载必须附注首发链接。谢谢。
-
手写深拷贝及深拷贝理解
2021-03-31 17:16:46手写深拷贝及深拷贝理解 前言 浅拷贝与深拷贝的关系 为什么使用深拷贝,深拷贝是干什么的? 浅拷贝 与深拷贝相对应的就是浅拷贝,浅拷贝就是直接赋值;在很多情况下我们都需要给变量赋值,给内存地址赋予一个值,...手写深拷贝及深拷贝理解
前言
- 浅拷贝与深拷贝的关系
- 为什么使用深拷贝,深拷贝是干什么的?
浅拷贝
与深拷贝相对应的就是浅拷贝,浅拷贝就是直接赋值;在很多情况下我们都需要给变量赋值,给内存地址赋予一个值,而在赋值引用类型时,只是共享一个内存区域,导致赋值的时候,还跟之前的值保持一至性。
var text1 = { a:1, b:2 } var text2 = text1 text2.a = 2 console.log(text1.a) // 2 console.log(text2.a) // 2
就如上面代码中直接给 text2 赋值 text1 只要改变 text2 的值,那么 text1 的值也会改变,那么这就要使用到我们的深拷贝,深拷贝就是给变量新建一个堆内存空间利用递归把数据赋值过去。
正文
要使用深拷贝那么就得先判断数据类型,确保是引用类型,因为数据类型不需要。
var obj = { name: '三石', age: '20', loveColor: 'black', hobby: { game: 'LOL', movement: 'running' }, game:['CF',"CS"] } var newObj = deepClone(obj) newObj.wocao[0]= "哈哈哈" console.log(obj) console.log(newObj) //深拷贝 function deepClone(obj) { // 判断obj是不是个对象或者是不是undefined //如果obj不是个对象或者是 undefined 或 null 直接进行 return if (typeof obj !== 'object' || obj == null) { return obj } // 初始化一个变量返回结果 let result // 判断obj的类型 然后给result一个一样的数据类型额 if (obj instanceof Array) { result = [] } else { result = {} } // 利用for in 遍历obj for (let key in obj) { if (obj.hasOwnProperty(key)) { // 下面这个判断可加可不加 看情况 如果死循环的话就加上 // 判断obj【key】是否存在 并且还是引用类型 if(obj[key] && typeof obj[key] === 'object'){ result[key] = deepClone(obj[key]) }else{ result[key] = obj[key] } } } return result }
小结
这只是es5的深拷贝写法,es6跟这个是有些差异,并且这只是深拷贝中的递归的写法。 -
python字典浅拷贝深拷贝 opencv mat浅拷贝深拷贝 c++对象浅拷贝深拷贝
2018-08-09 11:18:01dict2 = dict1.copy() #浅拷贝 拷贝一级对象,但是如果字典里有个列表,改变dict1中这个列表的值的时候,dict2相应改变,可以自己递归实现深拷贝 import copy dict2 = copy.deepcopy(dict1)#深拷贝所有级别的对象都...python字典 直接赋值 copy deepcopy
dict2 = dict1 #对象的引用 dict2 = dict1.copy() #浅拷贝 拷贝一级对象,但是如果字典里有个列表,改变dict1中这个列表的值的时候,dict2相应改变,可以自己递归实现深拷贝 import copy dict2 = copy.deepcopy(dict1)#深拷贝所有级别的对象都拷贝 浅拷贝只拷贝父对象的意思 a = {1: [1,2,3]} b = a.copy() #a, b分别为({1: [1, 2, 3]}, {1: [1, 2, 3]}) a[1].append(4) #a, b分别为({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
OpenCV mat 直接赋值//Mat image1(image) ;//仅是创建了Mat的头部分,image1与image共享数据区
cv::Mat image; cv::Mat image1(image) ;//仅是创建了Mat的头部分,image1与image共享数据区 cv::Mat image1 = image ;//仅是创建了Mat的头部分,image1与image共享数据区 cv::Mat image1 = image.clone() ;//深拷贝,把image中的所有信息拷贝到image1中 cv::Mat image1; image.copyTo(image1) ;//拷贝image的数据区到image1中,在拷贝数据前会有一步:image1.create(this->size , this->type) //注意 cv::Mat 作为函数参数,无论写不写& ,看似传值或者传引用这种方式,原图都会发生改变,不使用clone或者copyto或者手动赋值,都不是深拷贝,都共享数据区
c++ 拷贝构造函数的浅拷贝和深拷贝
c++中类对象的默认拷贝构造函数是浅拷贝,类a=类b,两个类的成员变量指向同一块内存,如果类b析构了之后,类a的成员变量还指向原来那块内存,就会有野指针的问题,会出错。
想要深拷贝,应该自己自定义拷贝构造函数,为对应的成员变量开辟新空间。这才是好的编程习惯。
//深拷贝的例子 class Example{ public: Example(int num, char* str) { num_ = num; str_ = new char[num]; strcpy(str_, str); } Example(const Example& e) { num_ = e.num; str_ = new char(num_); if(str_ != 0) strcpy(str_, e.str); } ~Example(){ delete str_; } private: int num_; char* str_; }
-
一篇文章彻底搞懂浅拷贝和深拷贝
2018-07-16 16:36:32强烈推荐30个原生JavaScript的demo,包括canvas时钟特效、自定义视频...【javascript】详解javaScript的深拷贝 目录 浅谈深拷贝和浅拷贝 深拷贝和浅拷贝的区别 为什么要使用深拷贝? 深拷贝的要求程度... -
Java 深拷贝 和 浅拷贝 clone
2019-11-27 16:15:22关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象。可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用传递将会... -
终于弄清楚JS的深拷贝和浅拷贝了-读这一篇就够了
2018-07-27 17:22:14今天,CVTE面试官问了深拷贝和浅拷贝的问题 我的回答是:浅拷贝是拷贝了对象的引用,当原对象发生变化的时候,拷贝对象也跟着变化;深拷贝是另外申请了一块内存,内容和原对象一样,更改原对象,拷贝对象不会发生... -
深拷贝和浅拷贝
2019-05-12 17:28:52深拷贝和浅拷贝的知识涉及到堆栈的概念。 堆栈的概念: 基本类型: 名值存储在栈内存中,例如: let a = 1; 引用类型: 名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值; 浅... -
深拷贝浅拷贝
2019-12-25 11:34:46深拷贝和浅拷贝的区别 1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用 2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,... -
BeanUtils.copyProperties的使用(深拷贝,浅拷贝)
2020-03-18 23:30:05这里说的是spring的BeanUtils.copyProperties。 场景 开发中经常遇到,把父类的属性拷贝到子类中。通常有2种方法: 1、一个一个set ...是深拷贝,还是浅拷贝? 是浅拷贝。 浅拷贝: 只是调用子对象的set... -
js 深拷贝与浅拷贝 以及深拷贝递归代码
2019-06-17 17:52:54深拷贝与浅拷贝的区别 假如复制A得到了B,如果B中的某个属性发生改变,与此同时如果A中的值也发生改变,叫浅拷贝; 如果A中的值未发生任何变化,叫做深拷贝; 为什么会发生如此变化 主要是因为数据类型的原因 ... -
Golang深拷贝浅拷贝
2019-05-30 23:19:37Golang深拷贝浅拷贝 在了解原型设计模式之前我们需要新知道Golang的深拷贝与浅拷贝之间的区别。 推荐大家新看看Slice 和 Map那么常见的坑:https://blog.csdn.net/weixin_40165163/article/details/90707593 ... -
深拷贝与浅拷贝的区别,实现深拷贝的几种方法
2018-08-28 11:09:49如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。 此篇文章中也会简单阐述到栈堆,基本... -
浅拷贝与深拷贝(三)代码实现深拷贝
2019-12-03 21:15:57代码实现深拷贝 经过对浅拷贝的简单了解,咱们就到了如何实现深拷贝的问题上,常见的循环遍历,只是遍历了一层数据,明显解决不了这个问题,不过咱们可以看出,深拷贝的问题不就在于怎么解决无限层级拷贝问题吗... -
JS浅拷贝,一层深拷贝,完全深拷贝【总结】
2018-07-15 21:10:42javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法 前言 在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示: 如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并... -
vue对象深拷贝_浅谈深拷贝和浅拷贝
2020-12-30 10:05:20深拷贝和浅拷贝说起深拷贝和浅拷贝,首先我们来看两个栗子// 栗子1var a = 1,b=a;console.log(a);console.log(b)b = 2;console.log(a);console.log(b)// 栗子2var obj1 = {x: 1, y: 2}, obj2 = obj1;console.log(obj... -
浅拷贝 VS 深拷贝,并且手写一个深拷贝(深克隆)
2020-06-24 08:30:481. 首先使用JSON.parse来实现一个深拷贝 let test = { x : 1, y : 2, z : { a : 4, b : 5 } } // 深拷贝 let result = JSON.parse(JSON.stringify(test)); // 改变拷贝后的值 result.z.a = 40; console.log... -
JS拷贝对象 浅克隆深克隆 深拷贝与浅拷贝,实现深拷贝的几种方法
2020-09-15 15:24:38js拷贝对象 浅克隆深克隆 深拷贝浅拷贝 对象简介 js程序中都是用对象结构来描述显示中一个事物,对象就是一组属性和方法的集合。 面向对象三大特点: 封装,继承,多态。 克隆对象 浅克隆是克隆 一层,深层次的对象... -
ECMAScript中的浅拷贝和深拷贝
2020-02-07 19:09:27一.什么是浅拷贝,什么是深拷贝 浅拷贝:浅拷贝是将原始对象中...深拷贝:深拷贝:深拷贝是在引用方面不同,深拷贝就是创建一个新的和原始字段的内容相同的字段,是两个一样大的数据段,所以两者的引用是不同的,之后... -
深拷贝的理解和如何手写一个深拷贝
2020-03-18 15:23:06深拷贝 说到深拷贝,肯定想到的最简单的方式就 JSON.stringify 和 JSON.parse 配合,这个是最简单的深拷贝方式 手写一个深拷贝 深拷贝 = 浅拷贝 + 递归 ,这个只是最笨的一种方式 var a = { name: "muyiy", book: {... -
ES5 深拷贝对象,深拷贝数组
2019-05-14 17:42:38* 深拷贝 */ //判断类型 function isType(arg) { var type = Object.prototype.toString.call(arg); type = (type.slice(8, type.length - 1)).toLowerCase(); return type; } //深拷贝对象 function deepFul..... -
Map深拷贝和对象深拷贝实现
2020-04-30 14:33:15所谓深拷贝就是将源对象克隆了一份保存在内存中,后续对复制的对象所有操作都不会影响源对象。 因为Map的putAll()的拷贝方式实现的是浅拷贝,所以后续对复制对象操作会影响到源对象。 在java中,对象的赋值都是对象... -
基础面试题:深拷贝和浅拷贝详解以及实例
2020-04-30 12:59:55深拷贝 vs 浅拷贝 浅拷贝 概念 复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。 如图: 特点 1.对于基本数据类型的成员对象,因为基础... -
-
深拷贝、浅拷贝区别,实现深拷贝的方法
2018-09-28 11:15:56如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。 此篇文章中也会简单阐述到栈堆,基本... -
深拷贝和浅拷贝区别是什么?
2019-06-18 15:44:47深拷贝和浅拷贝区别是什么? 复制一个 Java 对象 浅拷贝:复制基本类型的属性;引用类型的属性复制,复制栈中的变量 和 变量指向堆内存中的对象的指针,不复制堆内存中的对象。 深拷贝:复制基本类型的属性;...