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 相关文章推荐
Javascript中引用示例介绍
Feb 21 Javascript
JQuery实现超链接鼠标提示效果的方法
Jun 10 Javascript
jQuery的ajax和遍历数组json实例代码
Aug 01 Javascript
纯js模仿windows系统日历
Feb 04 Javascript
AngularJS ui-router (嵌套路由)实例
Mar 10 Javascript
JavaScript数据结构之链表的实现
Mar 19 Javascript
JavaScript类的继承方法小结【组合继承分析】
Jul 11 Javascript
vue1.0和vue2.0的watch监听事件写法详解
Sep 11 Javascript
Vue实现固定定位图标滑动隐藏效果
May 30 Javascript
Vue实现数据请求拦截
Oct 23 Javascript
node crawler如何添加promise支持
Feb 01 Javascript
详解Webpack抽离第三方类库以及common解决方案
Mar 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脚本的10个技巧(1)
2006/10/09 PHP
分享ThinkPHP3.2中关联查询解决思路
2015/09/20 PHP
一个简单的php MVC留言本实例代码(必看篇)
2016/09/22 PHP
实例讲解PHP表单验证功能
2019/02/15 PHP
JavaScript更改class和id的方法
2008/10/10 Javascript
jQuery EasyUI API 中文文档 - ComboTree组合树
2011/10/11 Javascript
原生javascript图片自动或手动切换示例附演示源码
2013/09/04 Javascript
鼠标悬浮显示二级菜单效果的jquery实现
2014/10/29 Javascript
JavaScript中使用自然对数ln的方法
2015/06/14 Javascript
php利用curl获取远程图片实现方法
2015/10/26 Javascript
Angular实现图片裁剪工具ngImgCrop实践
2017/08/17 Javascript
说说如何在Vue.js中实现数字输入组件的方法
2019/01/08 Javascript
微信小程序点击按钮动态切换input的disabled禁用/启用状态功能
2020/03/07 Javascript
jquery+css3实现的经典弹出层效果示例
2020/05/16 jQuery
如何实现小程序与小程序之间的跳转
2020/11/04 Javascript
深入理解python对json的操作总结
2017/01/05 Python
Python3学习笔记之列表方法示例详解
2017/10/06 Python
python中验证码连通域分割的方法详解
2018/06/04 Python
详解利用django中间件django.middleware.csrf.CsrfViewMiddleware防止csrf攻击
2018/10/09 Python
pytorch使用Variable实现线性回归
2019/05/21 Python
Django实现分页显示效果
2019/10/31 Python
Python实现图像去噪方式(中值去噪和均值去噪)
2019/12/18 Python
Windows 下更改 jupyterlab 默认启动位置的教程详解
2020/05/18 Python
python 写函数在一定条件下需要调用自身时的写法说明
2020/06/01 Python
使用HTML5的Notification API制作web通知的教程
2015/05/08 HTML / CSS
美国女性运动零售品牌:Lady Foot Locker
2017/05/12 全球购物
Origins悦木之源香港官网:雅诗兰黛集团高端植物护肤品牌
2018/03/21 全球购物
Radley英国官网:英国莱德利小狗包
2019/03/21 全球购物
应届生新闻编辑求职信
2013/11/19 职场文书
自我评价范文
2013/12/22 职场文书
书香家庭事迹材料
2014/05/09 职场文书
股票投资建议书
2014/05/19 职场文书
中级会计大学生职业生涯规划书
2014/09/16 职场文书
医生辞职信范文
2015/03/02 职场文书
2015年安全教育月活动总结
2015/03/26 职场文书
Django实现聊天机器人
2021/05/31 Python