js中的深浅拷贝问题简析


Posted in Javascript onMay 10, 2019

前言

在开发过程中,偶尔会遇到这种场景,拿到一个数据后,你打算对它进行处理,但是你又希望拷贝一份副本出来,方便数据对比和以后恢复数据。

那么这就涉及到了 JS 中对数据的深浅拷贝问题,所谓深浅拷贝,浅拷贝的意思就是,你只是复制了对象数据的引用,并没有把内存里的值另外复制一份,那么深拷贝就是把值完整地复制一份新的值。

下面这篇文章就对js中的深浅拷贝进行了深入的讲解,下面话不多说了,来一起看看详细的介绍吧

问题描述:

因为在JavaScript中对象在赋值中存储的是对象的地址(指针),所以会造成对象类型在复制过程中只复制对象的地址,从而导致以下问题

var people = {
 name: "小明"
 }
var peoplea = people;
peoplea.name = "小白";
console.log(peoplea.name)//小白
console.log(people.name)//小白

我们本来期望只改变peoplea的name,现在连people的name都改变了。根据情况的不同,可使用深拷贝或浅拷贝来解决。

解决方法:

我们在实现深浅拷贝之前,我们先看一看深、浅拷贝、赋值这三种的区别:

1、赋值

改变新对象时不管第几层,老对象都会随着变化。

var people = {
 name: "小明",
 act: ["吃饭","睡觉"]
}
var people1 = people;//赋值
people1.name = "小红";
 people1.act[1] = "打游戏";
console.log(people.name);//小红
console.log(people.act);//["吃饭", "打游戏"]

2、浅拷贝

改变新对象第一层基本数据类型时,老对象不变。有子对象时,改变子对象,老对象会随着变化。

var people = {
  name: "小明",
  act: ["吃饭", "睡觉"]
}
var people1 = Object.assign({}, people);//浅拷贝
people1.name = "小红";
people1.act[1] = "打游戏";
console.log(people.name);//小明
console.log(people.act);// ["吃饭", "打游戏"]

3、深拷贝

不管改变新对象第几层,老对象都不会随之改变。

var people = {
  name: "小明",
  act: ["吃饭", "睡觉"]
}
var people1 = JSON.parse(JSON.stringify(people));//深拷贝
people1.name = "小红";
people1.act[1] = "打游戏";
console.log(people.name);//小明
console.log(people.act);// ["吃饭", "睡觉"]

总结一下就是:

第一层为基本数据类型 多于一层含有子对象
赋值 新老一起改变 新老一起改变
浅拷贝 新对象改变,老对象不变 新老一起改变
深拷贝 新对象改变,老对象不变 新对象改变,老对象不变

了解完了区别,下面介绍实现深浅拷贝的几个方法。

一、浅拷贝

1、Object.assign()

官方对这个函数的介绍是:Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。实际上就是会把属性中的简单数据类型直接复制,而对于对象属性,只会拷贝地址(指针),上边介绍区别时用的就是这个;

var people1 = Object.assign({}, people);

需要注意的是,如果对象没有子对象,Object.assign()实现的就是深拷贝。

2、展开运算符(ES6新增)

var people = {
  name: "小明",
  act: ["吃饭", "睡觉"]
}
var people1 = {...people};
people1.name = "小红";
people1.act[1] = "打游戏";
console.log(people.name);//小明
console.log(people.act);// ["吃饭", "打游戏"]

3、自己写

var people = {
  name: "小明",
  act: ["吃饭", "睡觉"]
 }
 var people1 = shallowCopy(people);
 people1.name = "小红";
 people1.act[1] = "打游戏";
 console.log(people.name);//小明
 console.log(people.act);// ["吃饭", "打游戏"]
 function shallowCopy(obj) {
  var res = {};
  for (var index in obj) {
  if (obj.hasOwnProperty(index)) {//不复制原型链上的属性
   res[index] = obj[index];
  }
  }
  return res;
 }

二、深拷贝

1、JSON.parse(JSON.stringify(obj))

上边介绍区别时用的就是这个:

var people1 = JSON.parse(JSON.stringify(people));//深拷贝

这个方法比较简便但也存在问题

1、不能复制对象中的函数。

2、会忽略对象中的undefind。

2、lodash函数

官方介绍是:lodash是一个一致性、模块化、高性能的 JavaScript 实用工具库。官网是
www.lodashjs.com/ ,我推荐用其中的_.cloneDeep(value)方法。

ar objects = [{ "a": 1 }, { "b": 2 }];
 
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

还有自己去写一个递归,但是需要考虑的东西较多,不再赘述,也有用jq的$.extend()方法实现的,但是性能不好,这里提一下。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
基于Jquery+Ajax+Json的高效分页实现代码
Oct 29 Javascript
关于JavaScript与HTML的交互事件
Apr 12 Javascript
jQuery父级以及同级元素查找介绍
Sep 04 Javascript
jQuery获得内容和属性示例代码
Jan 16 Javascript
用jQuery实现的智能隐藏、滑动效果的返回顶部代码
Mar 18 Javascript
jQuery通过Ajax返回JSON数据
Apr 28 Javascript
JavaScipt选取文档元素的方法(推荐)
Aug 05 Javascript
微信小程序网络封装(简单高效)
Aug 06 Javascript
浅谈关于iview表单验证的问题
Sep 29 Javascript
vue 保留两位小数 不能直接用toFixed(2) 的解决
Aug 07 Javascript
JavaScript常用工具函数库汇总
Sep 17 Javascript
Vue实现穿梭框效果
Sep 30 Javascript
解决cordova+vue 项目打包成APK应用遇到的问题
May 10 #Javascript
详解jQuery如何实现模糊搜索
May 10 #jQuery
JS匿名函数内部this指向问题详析
May 10 #Javascript
详解关于React-Router4.0跳转不置顶解决方案
May 10 #Javascript
Vue使用watch监听一个对象中的属性的实现方法
May 10 #Javascript
微信小程序获取用户信息并保存登录状态详解
May 10 #Javascript
jsonp实现百度下拉框功能的方法分析
May 10 #Javascript
You might like
PHP中return 和 exit 、break和contiue 区别与用法
2012/04/09 PHP
深入apache配置文件httpd.conf的部分参数说明
2013/06/28 PHP
用PHP代替JS玩转DOM的思路及示例代码
2014/06/15 PHP
PHP与jquery实时显示网站在线人数实例详解
2016/12/02 PHP
浅析PHP类的反射来实现依赖注入过程
2018/02/06 PHP
用javascript自动显示最后更新时间
2007/03/15 Javascript
基于jQuery的弹出警告对话框美化插件(警告,确认和提示)
2010/06/10 Javascript
P3P Header解决Cookie跨域的问题
2013/03/12 Javascript
检查输入的是否是数字使用keyCode配合onkeypress事件
2014/01/23 Javascript
javascript实现控制的多级下拉菜单
2015/07/05 Javascript
前端性能优化及技巧
2016/05/06 Javascript
Js调用Java方法并互相传参的简单实例
2016/08/11 Javascript
JS实现表单多文件上传样式美化支持选中文件后删除相关项
2016/09/30 Javascript
JavaScript Uploadify文件上传实例
2017/02/28 Javascript
React Native之TextInput组件解析示例
2017/08/22 Javascript
JS实现HTML页面中动态显示当前时间完整示例
2018/07/30 Javascript
[02:05]2014DOTA2西雅图国际邀请赛 BBC第二天小组赛总结
2014/07/11 DOTA
天翼开放平台免费短信验证码接口使用实例
2013/12/18 Python
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
2014/06/10 Python
Python3里的super()和__class__使用介绍
2015/04/23 Python
python图片验证码生成代码
2016/07/02 Python
Python实战购物车项目的实现参考
2019/02/20 Python
Python实现的文轩网爬虫完整示例
2019/05/16 Python
python实现kNN算法识别手写体数字的示例代码
2019/08/16 Python
PyTorch中permute的用法详解
2019/12/30 Python
Pandas时间序列:时期(period)及其算术运算详解
2020/02/25 Python
荷兰最大的儿童服装店:The Kids Republic
2019/04/13 全球购物
科颜氏英国官网:Kiehl’s英国
2019/11/20 全球购物
武汉英思工程科技有限公司–ORACLE面试测试题目
2012/04/30 面试题
开业庆典邀请函
2014/01/08 职场文书
离职证明标准格式
2014/09/15 职场文书
教师学习八项规定六项禁令思想汇报
2014/09/27 职场文书
行政主管岗位职责范本
2015/04/09 职场文书
MySQL复制问题的三个参数分析
2021/04/07 MySQL
react中props 的使用及进行限制的方法
2021/04/28 Javascript
GO中sync包自由控制并发示例详解
2022/08/05 Golang