当前位置: 首页 > news >正文

JavaScript数组对象的浅拷贝与深拷贝(二)实现对象深拷贝的方法(5种)

JavaScript实现对象深拷贝的方法(5种)

  • 知识回调(不懂就看这儿!)
  • 场景复现
  • 实现对象深拷贝的五种方法
    • 1.json暴力转化
    • 2.es6扩展运算符
    • 3.for in循环遍历对象
    • 4.Object.assign()对象的合并
    • 5.利用循环和递归的方式
  • 实现对象浅拷贝的三种方法
    • 1.concat、slice返回一个新数组
    • 2.Object.assign()方法
    • 3.遍历对象(通用方法)

知识回调(不懂就看这儿!)

知识专栏专栏链接
JavaScript知识专栏https://blog.csdn.net/xsl_hr/category_12024214.html?spm=1001.2014.3001.5482
JavaScript深浅拷贝的区别+图解原理https://blog.csdn.net/XSL_HR/article/details/129838095?spm=1001.2014.3001.5501

有关JavaScript的相关知识可以前往JavaScript知识专栏查看复习!!

场景复现

在上期文章中,我们从底层原理方面对JavaScript数组对象的浅拷贝和深拷贝进行了详细的介绍,看完上期文章之后,想必大家对浅拷贝与深拷贝都有了一定的认识,而本期文章将分享五个非常实用的深拷贝方法和三个实用的浅拷贝方法

好的深拷贝方法有什么作用

  • 首先,深拷贝的学习对于我们在项目开发中进行数据处理是非常有用的。
  • 深拷贝原理和方法的学习能够帮助我们规范代码,提高代码的有效性。
  • 通知深拷贝方法的学习能够更好地帮助我们解决因为拷贝方式不当而产生的bug。节约更多debug的时间。

下面我们来通过代码示例来详细介绍五种深拷贝的方法。 👇👇👇

实现对象深拷贝的五种方法

1.json暴力转化

通过JSON.stringify()JSON.parse() 将对象转为字符串之后在转为对象。

var obj = {name:'123'}
var obj2 = JSON.parse(JSON.stringify(obj))
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}]
var new_arr = JSON.parse(JSON.stringify(arr))
console.log(new_arr);
  • 这种简单粗暴的方式有局限性,当值为undefinedfunctionsymbol会在转换过程中被忽略。
  • JSON.stringify()不仅可拷贝数组还能拷贝对象(但不能拷贝函数,也不能解决循环引用问题)

2.es6扩展运算符

var obj = {name:'123',age:13};
var obj2 = {...obj}

只能深度拷贝对象的第一层如果对象中的属性也是对象的话,没有办法进行深度拷贝的

3.for in循环遍历对象

  var obj = {name: "小明",age: 20}var obj1 = {}for (var key in obj) {//遍历属性值,深拷贝obj1[key] = obj[key]}console.log(obj1);
var deepCopy = function(target) {// 只拷贝对象if (typeof target !== 'object') return target;// 根据obj的类型判断是新建一个数组还是一个对象var result = Array.isArray(obj) ? [] : {};for (var key in target) {// 遍历obj,并且判断是obj的属性才拷贝(不能拷贝原型对象的属性)if (target.hasOwnProperty(key)) {// 判断属性值的类型,如果是对象递归调用深拷贝result[key] = typeof target[key] === 'object' ? deepCopy(target[key]) : target[key];}}return result;
}

其中上述方法一、方法三都解决不了循环引用的问题。

4.Object.assign()对象的合并

利用Object.assign(), 第一个参数必须是空对象

var obj = {name:'123',age:13};
var obj2 = Object.assign({},obj1);

5.利用循环和递归的方式

function deepClone(obj, newObj) {var newObj = newObj || {};for (let key in obj) {if (typeof obj[key] == 'object') {newObj[key] = (obj[key].constructor === Array) ? [] : {}deepClone(obj[key], newObj[key]);} else {newObj[key] = obj[key]}}return newObj;
}

在循环递归中需要注意设置临界值(typeof obj[key] == ‘object’),否则会造成死循环。
循环递归可以处理对象中嵌套数组或对象的问题。相当于第三种方法的优化。

实现对象浅拷贝的三种方法

1.concat、slice返回一个新数组

数组的浅拷贝可用concatslice返回一个新数组的特性来实现拷贝

var arr = ['old', 1, true, null, undefined];
var new_arr = arr.concat(); // 或者var new_arr = arr.slice()也是一样的效果;
new_arr[0] = 'new';
console.log(arr); // ["old", 1, true, null, undefined]
console.log(new_arr); // ["new", 1, true, null, undefined]

2.Object.assign()方法

let target = {};
let source = { a: { b: 2 } };
Object.assign(target, source);
console.log(target); // { a: { b: 10 } }; 
source.a.b = 10; 
console.log(source); // { a: { b: 10 } }; 
console.log(target); // { a: { b: 10 } };

但是如果数组嵌套了对象或者数组的话用concatslice拷贝只要有修改会引起新旧数组都一起改变了,比如:

var arr = [{old: 'old'}, ['old']];
var new_arr = arr.concat();
arr[0].old = 'new';
new_arr[1][0] = 'new';
console.log(arr); // [{old: 'new'}, ['new']]
console.log(new_arr); // [{old: 'new'}, ['new']]

3.遍历对象(通用方法)

实现思路遍历对象,把属性和属性值都放在一个新的对象里

var shallowCopy = function (obj) {// 只拷贝对象if (typeof obj !== 'object') return;// 根据obj的类型判断是新建一个数组还是一个对象var newObj = Array.isArray(obj) ? [] : {};// 遍历obj,并且判断是obj的属性才拷贝for (var key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = obj[key];}}return newObj;
}
  • 如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化。这种叫浅拷贝
  • 深拷贝就是指完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个

以上就是关于实现对象深拷贝与浅拷贝的方法的分享,相信看完这篇文章的小伙伴们一定能运用这些方法在项目开发中。当然,可能有不足的地方,欢迎大家在评论区留言指正!

下期文章将介绍vue antd项目实战中的深拷贝使用~
感兴趣的小伙伴可以订阅本专栏,方便后续了解学习~
觉得这篇文章有用的小伙伴们可以点赞➕收藏➕关注哦~
![在这里插入图片描述](https://img-blog.csdnimg.cn/a02b0a2c51f34d9bafe8754d275ead74.gif)
http://www.lryc.cn/news/43955.html

相关文章:

  • iPhone屏幕适配(之屏幕尺寸)
  • 手机变砖修复神器之 8 个的 Android手机系统修复工具
  • 稀疏矩阵(Sparse Matrix)
  • 深度学习中的损失函数
  • English Learning - L2 语音作业打卡 辅音咬舌音 [θ] [ð] Day29 2023.3.21 周二
  • 【原始者-综述】
  • C++内存模型
  • 八股+面经
  • MySQL更新数据流程
  • 测试开发进阶系列课程
  • Qt源码阅读(三) 对象树管理
  • 【Python入门第四十二天】Python丨NumPy 数组裁切
  • Anaconda配置Python新版本tensorflow库(CPU、GPU通用)的方法
  • 加载模型时出现 OSError: Unable to load weights from pytorch checkpoint file 报错的解决
  • sessionStorage , localStorage 和cookie的区别
  • C# 实例详解委托之Func、Action、delegate
  • 如何选电脑
  • SpringBoot项目创建
  • 神经衰弱该如何判断?确诊为神经衰弱,日常要做好这7大护理!
  • Linux之进程替换
  • 关于清除浮动
  • Uber H3 index 地图索引思考
  • 多线程的几种状态
  • 【算法题】1574. 删除最短的子数组使剩余数组有序
  • 理解对数——金融问题中的自然对数(以e为底的对数)
  • vue2进阶学习之路
  • 决策树ID3算法
  • C++模板基础(一)
  • 生产者消费者模型线程池(纯代码)
  • K8s 应用的网络可观测性: Cilium VS DeepFlow