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 相关文章推荐
idTabs基于JQuery的根据URL参数选择Tab插件
Apr 11 Javascript
在JavaScript里嵌入大量字符串常量的实现方法
Jul 07 Javascript
在服务端(Page.Write)调用自定义的JS方法详解
Aug 09 Javascript
JQuery文本改变触发事件如聚焦事件、失焦事件
Jan 15 Javascript
AngularJS实现表单验证
Jan 28 Javascript
javascript事件的绑定基础实例讲解(34)
Feb 14 Javascript
详解用webpack把我们的业务模块分开打包的方法
Jul 20 Javascript
Node.js+jade抓取博客所有文章生成静态html文件的实例
Sep 19 Javascript
浅谈手写node可读流之流动模式
Jun 01 Javascript
微信小程序页面缩放式侧滑效果的实现代码
Nov 15 Javascript
详解jQuery-each()方法
Mar 13 jQuery
Vue2.x和Vue3.x的双向绑定原理详解
Nov 05 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 源代码压缩小工具
2009/12/22 PHP
php中将数组转成字符串并保存到数据库中的函数代码
2013/09/29 PHP
PHP缓存集成库phpFastCache用法
2014/12/15 PHP
PHP实现事件机制实例分析
2015/06/26 PHP
PHP内核探索:哈希表碰撞攻击原理
2015/07/31 PHP
PHP附件下载中文名称乱码的解决方法
2015/12/17 PHP
JavaScript为对象原型prototype添加属性的两种方式
2010/08/01 Javascript
js判断上传文件的类型和大小示例代码
2013/10/18 Javascript
Jquery实现控件的隐藏和显示实例
2014/02/08 Javascript
浅析JQuery中的html(),text(),val()区别
2014/09/01 Javascript
基于JS判断iframe是否加载成功的方法(多种浏览器)
2016/05/13 Javascript
浅谈jquery.form.js的ajaxSubmit和ajaxForm的使用
2016/09/09 Javascript
AngularJS压缩JS技巧分析
2016/11/08 Javascript
用jQuery实现优酷首页轮播图
2017/01/09 Javascript
Vue实现数字输入框中分割手机号码的示例
2017/10/10 Javascript
JavaScript继承与多继承实例分析
2018/05/26 Javascript
js实现每日签到功能
2018/11/29 Javascript
原来JS还可以这样拆箱转换详解
2019/02/01 Javascript
Django中对数据查询结果进行排序的方法
2015/07/17 Python
浅谈python socket函数中,send与sendall的区别与使用方法
2017/05/09 Python
根据DataFrame某一列的值来选择具体的某一行方法
2018/07/03 Python
解决python中使用plot画图,图不显示的问题
2018/07/04 Python
python如何使用Redis构建分布式锁
2020/01/16 Python
安装完Python包然后找不到模块的解决步骤
2020/02/13 Python
matlab 计算灰度图像的一阶矩,二阶矩,三阶矩实例
2020/04/22 Python
css3 box-sizing属性使用参考指南
2013/01/08 HTML / CSS
使用HTML5在网页中嵌入音频和视频播放的基本方法
2016/02/22 HTML / CSS
美国顶级奢侈茶:Mighty Leaf Tea(美泰茶)
2016/11/26 全球购物
新电JAVA笔试题目
2014/08/31 面试题
学生周末回家住宿长期请假条
2014/02/15 职场文书
大学校务公开实施方案
2014/03/31 职场文书
2014年社区工会工作总结
2014/12/18 职场文书
2015年学校安全工作总结
2015/04/22 职场文书
2015年医院后勤工作总结
2015/05/20 职场文书
大学生党课感想
2015/08/11 职场文书
股东协议书范本2016
2016/03/21 职场文书