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 学习之旅 (2)
Feb 05 Javascript
用JQuery在网页中实现分隔条功能的代码
Aug 09 Javascript
js原型链与继承解析(初体验)
May 09 Javascript
异步加载JS、CSS代码(推荐)
Jun 15 Javascript
浅谈$_FILES数组为空的原因
Feb 16 Javascript
bootstrap可编辑下拉框jquery.editable-select
Oct 12 jQuery
vue中img src 动态加载本地json的图片路径写法
Apr 25 Javascript
vue-cli3+ts+webpack实现多入口多出口功能
May 30 Javascript
javascript 构建模块化开发过程解析
Sep 11 Javascript
Vue实现 点击显示再点击隐藏效果(点击页面空白区域也隐藏效果)
Jan 16 Javascript
详解Vue 单文件组件的三种写法
Feb 19 Javascript
vant picker+popup 自定义三级联动案例
Nov 04 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的字符串用法小结
2010/06/08 PHP
PHP判断表单复选框选中状态完整例子
2014/06/24 PHP
php返回当前日期或者指定日期是周几
2015/05/21 PHP
PHP+redis实现添加处理投票的方法
2015/11/14 PHP
[原创]用javascript实现检测指定目录是否存在的方法
2008/01/12 Javascript
javascript getElementsByClassName函数
2010/04/01 Javascript
File, FileReader 和 Ajax 文件上传实例分析(php)
2011/04/27 Javascript
巧用js提交表单轻松解决一个页面有多个提交按钮
2013/11/17 Javascript
javascript数字时钟示例分享
2014/04/23 Javascript
JavaScript中Function详解
2015/02/27 Javascript
实例讲解jQuery中对事件的命名空间的运用
2016/05/24 Javascript
AngularJS基础 ng-model 指令详解及示例代码
2016/08/02 Javascript
详解JS中的快速排序与冒泡
2017/01/10 Javascript
JavaScript在form表单中使用button按钮实现submit提交方法
2017/01/23 Javascript
JavaScript仿微信打飞机游戏
2020/07/05 Javascript
AngularJs用户登录问题处理(交互及验证、阻止FQ处理)
2017/10/26 Javascript
轻松理解vue的双向数据绑定问题
2017/10/30 Javascript
js中对象和面向对象与Json介绍
2019/01/21 Javascript
微信小程序页面间传递数组对象方法解析
2019/11/06 Javascript
javascript使用canvas实现饼状图效果
2020/09/08 Javascript
[52:39]完美世界DOTA2联赛PWL S3 CPG vs Forest 第一场 12.16
2020/12/17 DOTA
python删除文件示例分享
2014/01/28 Python
自动化Nginx服务器的反向代理的配置方法
2015/06/28 Python
Python中注释(多行注释和单行注释)的用法实例
2019/08/28 Python
Python列表原理与用法详解【创建、元素增加、删除、访问、计数、切片、遍历等】
2019/10/30 Python
python实现canny边缘检测
2020/09/14 Python
宝拉珍选官方旗舰店:2%水杨酸精华液,收缩毛孔粗大和祛痘
2018/07/01 全球购物
美国狗旅行和户外用品领先供应商:kurgo
2020/08/18 全球购物
最新自我评价范文
2013/11/16 职场文书
九年级政治教学反思
2014/02/06 职场文书
自强之星事迹材料
2014/05/12 职场文书
教师党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
检讨书怎么写?
2019/06/21 职场文书
Python实现GIF动图以及视频卡通化详解
2021/12/06 Python
Python matplotlib可视化之绘制韦恩图
2022/02/24 Python
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
2022/03/16 Redis