js实现深拷贝的几种方法

JavaScript05

js实现深拷贝的几种方法,第1张

简单来说,深拷贝主要是将另一个对象的属性值拷贝过来之后,另一个对象的属性值并不受到影响,因为此时它自己在堆中开辟了自己的内存区域,不受外界干扰。

浅拷贝主要拷贝的是对象的引用值,当改变对象的值,另一个对象的值也会发生变化。

使用 js ON.stringify和 js ON.parse实现深拷贝:JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象;

缺陷:它会抛弃对象的 const ructor,深拷贝之后,不管这个对象原来的构造 函数 是什么,在深拷贝之后都会变成Object;这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,也就是说,只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON;

递归拷贝实现深拷贝,解决循环引用问题

首先,有关【递归】的知识请参考上一节,链接地址:

【上一篇】:带你刷LeetCode中的递归算法

根据JS中【栈】的知识,我们知道js的基本数据类型是值引用,引用类型是地址引用。在浅拷贝中引用的地址同一个地址引用,修改其中一个对象的属性值,另一个对象也会产生影响;而在深拷贝中,会开辟一个新的内存地址用来存放新对象的值,两个对象对应引用的内存地址不一样 ,修改一个对象并不会对另外一个对象产生影响。更详细的描述请参考关于【栈】的介绍。

【栈】:JS版数据结构-栈

一个新的对象直接拷贝已存在的对象的对象属性的引用,即浅拷贝。

对于以上两个拷贝,obj中的name是基本数据类型,浅拷贝可以直接赋值得到,msg是个对象,是复杂数据类型,对象会开辟一个新的内存空间存储msg对象,浅拷贝的时候时拷贝的地址是同一个地址。此时改变obj中的txt中的值,o中的txt的值也会改变。

对于数组的拷贝,可以利用数组原型上内置的slice方法。

数组合并也是一个浅拷贝。

深拷贝会另外拷贝一份一个一模一样的对象,从堆内存中开辟一个新的区域存放新对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

简单说:深拷贝把存放对象的空间地址,再复制一份给新对象,这样两个对象直接互不干扰。

基于基本数据类型直接循环复制,对于复杂数据类型再次运用for循环操作,每一级都要循环拷贝。我们可以使用递归,对于遇到对象再次调用for循环即可。

下一篇:JS中的算法.排序

推荐阅读:

1. JS. 类

2. JS. 构造函数

3. JS中对象原型 proto 及原型链

4. JS. 构造函数的原型 prototype

一、 错误实现

var array1 = new Array("1","2","3") 

var array2 

array2 = array1 

array1.length = 0 

alert(array2) //返回为空

这种做法是错的,因为javascript分原始类型与引用类型(与java、c#类似)。Array是引用类

型。array2得到的是引用,所以对array1的修改会影响到array2。

二、 使用slice()

可使用slice()进行复制,因为slice()返回也是数组。

var array1 = new Array("1","2","3") 

var array2 

array2 = array1.slice(0) 

array1.length = 0 

alert(array2) //返回1、2、3 

三、 使用concat()

注意concat()返回的并不是调用函数的Array,而是一个新的Array,所以可以利用这一点进行复制。

var array1 = new Array("1","2","3") 

var array2 

array2 = array1.concat() 

array1.length = 0 

alert(array2) //返回1、2、3