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 文档碎片
Jul 13 Javascript
jQuery1.9.1针对checkbox的调整方法(prop)
May 01 Javascript
javascript浏览器窗口之间传递数据的方法
Jan 20 Javascript
在WordPress中加入Google搜索功能的简单步骤讲解
Jan 04 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
Feb 09 Javascript
Bootstrap如何激活导航状态
Mar 22 Javascript
基于jquery实现五星好评
Nov 18 jQuery
vue2.0 资源文件assets和static的区别详解
Apr 08 Javascript
JS获取当前时间的实例代码(昨天、今天、明天)
Nov 13 Javascript
js中null与空字符串""的区别讲解
Jan 17 Javascript
JavaScript文档加载模式以及元素获取
Jul 28 Javascript
解析原生JS getComputedStyle
May 25 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获取服务器时间的实现代码
2013/06/07 PHP
基于PHP实现假装商品限时抢购繁忙的效果
2015/10/16 PHP
smarty简单应用实例
2015/11/03 PHP
thinkphp制作404跳转页的简单实现方法
2016/09/22 PHP
解决laravel id非自增 模型取回为0 的问题
2019/10/11 PHP
js获取url参数的使用扩展实例
2007/12/29 Javascript
jQuery之网页换肤实现代码
2011/04/30 Javascript
JavaScript加入收藏夹功能(兼容IE、firefox、chrome)
2014/05/05 Javascript
仿JQuery输写高效JSLite代码的一些技巧
2015/01/13 Javascript
jQuery 遍历函数详解
2015/07/05 Javascript
使用原生的javascript来实现轮播图
2017/02/24 Javascript
使用grunt合并压缩js和css文件的方法
2017/03/02 Javascript
一个简易时钟效果js实现代码
2020/03/25 Javascript
nodejs实现的连接MySQL数据库功能示例
2018/01/25 NodeJs
jQuery插件Validation表单验证详解
2018/05/26 jQuery
玩转Koa之koa-router原理解析
2018/12/29 Javascript
你不可不知的Vue.js列表渲染详解
2019/10/01 Javascript
OpenLayers实现图层切换控件
2020/09/25 Javascript
[01:34]完美“圣”典宣传片震撼发布,12.17与你不见不散
2016/12/16 DOTA
python实现的各种排序算法代码
2013/03/04 Python
python字符串连接方式汇总
2014/08/21 Python
python爬虫爬取淘宝商品信息
2018/02/23 Python
解决pyinstaller打包发布后的exe文件打开控制台闪退的问题
2019/06/21 Python
关于Pytorch MaxUnpool2d中size操作方式
2020/01/03 Python
CSS3 网页下拉菜单代码解释 中文翻译
2010/02/27 HTML / CSS
孤独星球出版物:Lonely Planet Publications
2018/03/17 全球购物
资产评估专业大学生求职信
2013/09/29 职场文书
大学生专业个人学习的自我评价
2013/10/26 职场文书
办公室主任职责范文
2013/11/08 职场文书
竟聘演讲稿范文
2013/12/31 职场文书
财产公证书格式
2014/04/10 职场文书
英语自我介绍演讲稿
2014/09/01 职场文书
2019年员工晋升管理制度范本!
2019/07/08 职场文书
英文诗歌翻译方法(赏析)
2019/08/16 职场文书
解析mybatis-plus中的resultMap简单使用
2021/11/23 Java/Android
vue项目配置sass及引入外部scss文件
2022/04/14 Vue.js