首页 > temp > JavaScript教程 >
-
JavaScript实现数据拷贝的方法
前言
在我们日常开发过程中,常遇到这种场景,在拿到一份数据后,你打算对它进行处理,但是你不想在原先的基础上进行改变而是希望拷贝一份副本出来,方便对数据比较和以后恢复数据。
那么这就涉及到了 JS 中对数据的深浅拷贝问题。
我们知道JS 中的数据类型可分为两种,基本数据类型(7种)和引用数据类型(2种),基本数据类型是保存在栈的数据结构中的,是按值访问,所以不存在深浅拷贝问题。
而比如对象,数组,函数,正则,时间对象这些都是引用数据类型,是保存在堆中的。
所以,引用数据类型的复制,是内存地址的传递,并没有拷贝出一份新的数据。
先来看两个概念深拷贝和浅拷贝的区别:
上面说过,首先深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
浅拷贝:遍历对象中的内容,一个一个的进行赋值,这样只进行一层拷贝的方式了,就是浅拷贝。
深拷贝:不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。
所以检测是否深浅拷贝的方法是:
由obj1拷贝得obj2,修改obj2里面的对象或者数组的值,obj1里的象或者数组值发生变化叫浅拷贝,反之叫深拷贝。
那么js有哪些方法实现对象的拷贝呢?
常用的方法有如下几种:
①、JSON.parse(JSON.stringify(obj))
方法(深拷贝)
②、Object.assign()方法(浅拷贝)
③、使用递归方法(深拷贝)
④、Jquery的$.extend( [deep ], target, object1 [, objectN ] )方法(deep:true深拷贝,deep:false浅拷贝)
下面用具体的代码来说明每个方法实现拷贝功能的用法以及深、浅拷贝的区别。
注意:在使用$.extend方法时需要先引入<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.js"></script> <script> var Person = function() { return { basicMessage:{ name:'zhangsan', }, hobby:['coding'], firstName:'zhang' } } //---------------------------------------------方法一----------------------------------------------------------// // ①、JSON.parse(JSON.stringify(obj))方法(深拷贝) var person = Person(); var person_1_deep = JSON.parse(JSON.stringify(person)); person_1_deep.firstName = 'Li'; // 字符窜类型 person_1_deep.basicMessage.name = 'LiSi'; // 对象类型 person_1_deep.hobby.push('sleepping'); console.log("%cJSON.parse(JSON.stringify(obj))方法(深拷贝):","background:rgba(252,234,187,1)"); console.log(person); //---------------------------------------------方法二----------------------------------------------------------// // ②、Object.assign()方法(浅拷贝) var person = Person(); var person_2_deep = Object.assign({},person); person_2_deep.firstName = 'Li'; // 字符窜类型 person_2_deep.basicMessage.name = 'LiSi'; // 对象类型 person_2_deep.hobby.push('sleepping'); console.log("%cObject.assign()方法(浅拷贝):","background:rgba(252,234,187,1)"); console.log(person); //---------------------------------------------方法三----------------------------------------------------------// // ③、使用递归方法(深拷贝) function copy(source) { let target; if (typeof source ==='object') { target = Array.isArray(source)?[]:{}; for(let key in source){ if (source.hasOwnProperty(key)) { if (typeof source[key] !=='object') { target[key] = source[key]; } else { target[key] = copy(source[key]); // 递归处理对象 } } } } else { target = source; } return target; } var person = Person(); var person_3_deep = copy(person); person_3_deep.firstName = 'Li'; // 字符窜类型 person_3_deep.basicMessage.name = 'LiSi'; // 对象类型 person_3_deep.hobby.push('sleepping'); console.log("%c手写递归(深拷贝):","background:rgba(252,234,187,1)"); console.log(person); //---------------------------------------------方法四----------------------------------------------------------// // ④、Jquery的$.extend( [deep ], target, object1 [, objectN ] )方法(deep:true深拷贝,deep:false浅拷贝) // 深拷贝 var person = Person(); var person_4_deep = $.extend(true,{},person); person_4_deep.firstName = 'Li'; // 字符窜类型 person_4_deep.basicMessage.name = 'LiSi'; // 对象类型 person_4_deep.hobby.push('sleepping'); console.log("%c$.extend(深拷贝):","background:rgba(252,234,187,1)"); console.log(person); // 浅拷贝 var person = Person(); var person_4_shallow = $.extend(false,{},person); person_4_shallow.firstName = 'Li'; // 字符窜类型 person_4_shallow.basicMessage.name = 'LiSi'; // 对象类型 person_4_shallow.hobby.push('sleepping'); console.log("%c$.extend(浅拷贝):","background:rgba(252,234,187,1)"); console.log(person); </script>
四种方法打印出的结果以及深浅拷贝对比如下:
打印出结果后相信大家对深浅拷贝的区别已经一目了然:
在每种方法里面对拷贝后的数据做了同样的修改,修改了拷贝后数据的数组和对象的值,
在浅拷贝中原来数据的数组或对象发生了改变,而在深拷贝中原数据一点不变。
上述代码地址请访问:https://github.com/tianshiliang/javascript-
出处:https://www.cnblogs.com/tsl0324/p/14508799.html