经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
带你搞懂js的深拷贝
来源:jb51  时间:2021/11/15 20:02:49  对本文有异议

js深拷贝

在讲正题之前我们要先了解数据存储的方式

数据存储方式

在讲之前我们要先知道值类型和引用类型的存储方式。

在JavaScript数据类型中有两种数据类型。

值类型:字符串(String)、数字 (Number)、布尔 (Boolean)、空(Null)、未定义(Undefined)、Symbol

存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。

引用数据类型:对象 (Object) 、数组 (Array) 、函数 (Function) 。

存放在堆内存中的对象,在栈内存中存的是一个指针,这个指针指向堆内存一个位置。再从堆内存中取得所需的数据。

存储如下图:

在这里插入图片描述

什么是浅/深拷贝

讲完存储的方式,我们来讲讲浅拷贝和深拷贝

拷贝也就是我们常常讲的copy,ctrl+c,ctrl+v,那么我们来看看例子

当我们对分别值类型和引用类型进行赋值。

  1. var a = 5
  2. var b = a
  3. b += 5
  4. console.log('a=' + a,'b=' + b)
  5. var arr=[1,2,3]
  6. var brr=arr
  7. brr.push(10)
  8. console.log("arr为",arr)
  9. console.log("brr为",brr)

在这里插入图片描述

现象:我们发现值类型并没有互相受到影响,然而数组(引用类型)brr数组添加元素的时候改变了arr数组。

解释分析:浅拷贝只会发生在引用类型身上,对于引用类型如果之进行简单的赋值,只会赋值指向堆内存的指针,这种称为浅拷贝。而深拷贝就是完全拷贝一个引用类型,为不是地址指针。

浅拷贝看下面这张原理图:

在这里插入图片描述

常用深拷贝实现

那么我们在赋值引用类型的时候肯定不能出现浅拷贝的现象,对原数据产生影响了。那么就要进行深拷贝

1.通过JSON.stringify和JSON.parse

可以深拷贝的数组和对象,但是不能拷贝函数,可以进行对象或者数组的嵌套拷贝。

缺点:无法实现对对象中方法的深拷贝

使用

  1. var brr=JSON.parse(JSON.stringify(arr))

例子:

  1. var arr = {
  2. name: '浪漫主义码农',
  3. age: 20,
  4. adress: ['jiangxi', 'changsha'],
  5. friends: {
  6. friend1: '张三',
  7. friend2: '李四'
  8. },
  9. function(){
  10. console.log("我是浪漫主义的对象")
  11. }
  12. }
  13. var brr=JSON.parse(JSON.stringify(arr))
  14. brr.name='法外狂徒张三'
  15. brr.adress[0]='长沙'
  16. console.log("arr为", arr)
  17. console.log("brr为", brr)

在这里插入图片描述

2.扩展运算符

利用了对象的结构赋值特性方法。

缺点:无对对象里面嵌套的对象进行深拷贝,相当于只是对一层引用对象进行深拷贝

使用:

  1. var brr={...arr}

例子:

  1. var arr = {
  2. name: '浪漫主义码农',
  3. age: 20,
  4. adress: ['jiangxi', 'changsha'],
  5. friends: {
  6. friend1: '张三',
  7. friend2: '李四'
  8. },
  9. function(){
  10. console.log("我是浪漫主义的对象")
  11. }
  12. }
  13. var brr={...arr}
  14. brr.name='法外狂徒张三'
  15. brr.adress[0]='长沙'
  16. console.log("arr为", arr)
  17. console.log("brr为", brr)

在这里插入图片描述

3.手写递归深拷贝函数

完美解决

函数:

  1. //使用递归实现深拷贝
  2. function deepClone(obj) {
  3. //判断拷贝的obj是对象还是数组
  4. var objClone = Array.isArray(obj) ? [] : {};
  5. if (obj && typeof obj === "object") { //obj不能为空,并且是对象或者是数组 因为null也是object
  6. for (key in obj) {
  7. if (obj.hasOwnProperty(key)) {
  8. if (obj[key] && typeof obj[key] === "object") { //obj里面属性值不为空并且还是对象,进行深度拷贝
  9. objClone[key] = deepClone(obj[key]); //递归进行深度的拷贝
  10. } else {
  11. objClone[key] = obj[key]; //直接拷贝
  12. }
  13. }
  14. }
  15. }
  16. return objClone;
  17. }

例子:

  1. var arr = {
  2. name: '浪漫主义码农',
  3. age: 20,
  4. adress: ['jiangxi', 'changsha'],
  5. friends: {
  6. friend1: '张三',
  7. friend2: '李四'
  8. },
  9. fun: function(){
  10. console.log("我是" + this.name + "的对象")
  11. }
  12. }
  13. var brr = deepClone(arr)
  14. brr.name = '法外狂徒张三'
  15. brr.adress[0] = '长沙'
  16. console.log("arr为", arr)
  17. arr.fun()
  18. console.log("brr为", brr)
  19. brr.fun()
  20. //使用递归实现深拷贝
  21. function deepClone(obj) {
  22. //判断拷贝的obj是对象还是数组
  23. var objClone = Array.isArray(obj) ? [] : {};
  24. if (obj && typeof obj === "object") { //obj不能为空,并且是对象或者是数组 因为null也是object
  25. for (key in obj) {
  26. if (obj.hasOwnProperty(key)) {
  27. if (obj[key] && typeof obj[key] === "object") { //obj里面属性值不为空并且还是对象,进行深度拷贝
  28. objClone[key] = deepClone(obj[key]); //递归进行深度的拷贝
  29. } else {
  30. objClone[key] = obj[key]; //直接拷贝
  31. }
  32. }
  33. }
  34. }
  35. return objClone;
  36. }

在这里插入图片描述

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注w3xue的更多内容!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号