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 document.referrer 用法
Apr 30 Javascript
DOM 基本方法
Jul 18 Javascript
Javascript在IE或Firefox下获取鼠标位置的代码
Dec 18 Javascript
鼠标移到导航当前位置的LI变色处于选中状态
Aug 23 Javascript
javascript 实现 原路返回
Jan 21 Javascript
jQuery消息提示框插件Tipso
May 04 Javascript
谈谈对offsetleft兼容性的理解
Nov 11 Javascript
javascript代码调试之console.log 用法图文详解
Sep 30 Javascript
详解基于webpack和vue.js搭建开发环境
Apr 05 Javascript
Vue实现todolist删除功能
Jun 26 Javascript
微信小程序中遇到的iOS兼容性问题小结
Nov 14 Javascript
详解Vue中的自定义指令
Dec 07 Vue.js
解决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
图书管理程序(三)
2006/10/09 PHP
NOT NULL 和NULL
2007/01/15 PHP
在项目中寻找代码的坏命名
2012/07/14 PHP
PHP实现微信公众平台音乐点播
2014/03/20 PHP
ThinkPHP中I(),U(),$this->post()等函数用法
2014/11/22 PHP
php文件上传简单实现方法
2015/01/24 PHP
漂亮的widgets,支持换肤和后期开发新皮肤(2007-4-27已更新1.7alpha)
2007/04/27 Javascript
Jquery数独游戏解析(一)-页面布局
2010/11/05 Javascript
JavaScript 作用域链解析
2014/11/13 Javascript
JS更改select内option属性的方法
2015/10/14 Javascript
JSON 数据详解及实例代码分析
2017/01/20 Javascript
基于MVC方式实现三级联动(JavaScript)
2017/01/23 Javascript
jquery设置css样式的多种方法(总结)
2017/02/21 Javascript
Bootstrap页面标题Page Header的实现方法
2017/03/22 Javascript
简单的Vue SSR的示例代码
2018/01/12 Javascript
Vue+ElementUI实现表单动态渲染、可视化配置的方法
2018/03/07 Javascript
使用Vue.js开发微信小程序开源框架mpvue解析
2018/03/20 Javascript
详解angular分页插件tm.pagination二次触发问题解决方案
2018/07/20 Javascript
简述pm2常用命令集合及配置文件说明
2019/05/30 Javascript
vue父子组件通信的高级用法示例
2019/08/29 Javascript
mui js控制开关状态、修改switch开关的值方法
2019/09/03 Javascript
JS实现购物车基本功能
2020/11/08 Javascript
Python的一些用法分享
2012/10/07 Python
Python基于有道实现英汉字典功能
2015/07/25 Python
浅谈python中的数字类型与处理工具
2017/08/02 Python
Python中的pygal安装和绘制直方图代码分享
2017/12/08 Python
Python多线程中阻塞(join)与锁(Lock)使用误区解析
2018/04/27 Python
Django框架验证码用法实例分析
2019/05/10 Python
Django实现文件上传和下载功能
2019/10/06 Python
荷兰超市:DEEN
2018/03/14 全球购物
高中班主任评语大全
2014/04/25 职场文书
护士实习求职信
2014/06/22 职场文书
司法工作人员群众路线对照检查材料思想汇报
2014/09/30 职场文书
中秋节晚会开场白
2015/05/29 职场文书
城南旧事观后感
2015/06/11 职场文书
《所见》教学反思
2016/02/23 职场文书