文章目录

  • 一、浅拷贝
  • 二、深拷贝
  • 三、判断深、浅拷贝
    • 1.concat()方法
    • 2.slice()方法
    • 3.Array.from()方法
    • 4.扩展运算符
  • 四、实现浅拷贝
    • 1.Object.assign方法
    • 2.for in方法
  • 五、实现深拷贝
    • 1.递归实现
    • 2.JSON.stringify与JSON.parse
    • 3.loadash函数库

一、浅拷贝

  浅拷贝和深拷贝都只针对于引用数据类型,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存
例如:

const obj_1 = {age: 21
}
const obj_2 = obj_1;    // 对象obj_2只复制了obj_1的地址
obj_2.age = 19;
console.log(obj_1.age);     // 输出:19

内存角度:对象obj_1会在中分配一个内存地址,该内存地址对应的值又会创建一个新的内存地址,该新的内存地址又指向这样一个数据结构,并在堆中创建对应的属性值age:21。而上述案例中创建obj_2并赋值obj_1,实际上只复制了指针,这么做将会导致obj_2与obj_1指向同一个地址,他们两从栈到堆这两种数据类型的链路都是一样的,obj_2修改属性age的值,导致obj_1中age的值发生改变,称作只实现了浅拷贝。

二、深拷贝

  不同于浅拷贝,深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象;

三、判断深、浅拷贝

  我们通过我们熟知的引用类型——数组,用其内置的一些方法判断是浅拷贝还是深拷贝

1.concat()方法

判断:

let list = ['我爱', '学习'];
let copyList = [].concat(list);
copyList.push('JavaScript');
console.log(list);      // ['我爱', '学习']
console.log(copyList);      // ['我爱', '学习', 'JavaScript']

  我们使用concat()方法拷贝副本,返回新构建的数组,此时我对新数组元素的添加也不会影响到原数组,然而。。。答案为:浅拷贝

2.slice()方法

判断:

let list = ['我爱', '学习'];
let copyList = list.slice();
copyList.push('JavaScript');
console.log(list);      // ['我爱', '学习']
console.log(copyList);      // ['我爱', '学习', 'JavaScript']

  我们使用slice()方法不传参的方式从头到尾拷贝副本,并且返回新数组,即使我对新数组添加元素也不会影响到原数组,然而。。。答案仍然为:浅拷贝

3.Array.from()方法

判断:

let list = ['我爱', '学习'];
let copyList = Array.from(list);
copyList.push('JavaScript');
console.log(list);      // ['我爱', '学习']
console.log(copyList);      // ['我爱', '学习', 'JavaScript']

  我们使用ES6中Array.from()方法同样以不影响原数组的方式实现了拷贝,然而。。。答案依旧为:浅拷贝

4.扩展运算符

判断:

let list = ['我爱', '学习'];
let copyList = [...list];
copyList.push('JavaScript');
console.log(list);      // ['我爱', '学习']
console.log(copyList);      // ['我爱', '学习', 'JavaScript']

  我们再次使用ES6中扩展运算符,同理:浅拷贝

我们来考证一下:

let list = [{ name: 'Tom' }];
let copyList = [...list];
copyList[0].name = 'Jerry'
console.log(list[0].name);      // Jerry
console.log(copyList[0].name);      // Jerry

  我们将数组元素都换成引用类型,执行以上方法,并通过拷贝副本改变数组元素的值,我们会发现原数组的元素也发生了改变,由此可见,确实是浅拷贝。除此之外,数组的其他方法如map()、filter()、reduce(),都是会造成浅拷贝的。

四、实现浅拷贝

1.Object.assign方法

let list = {obj: {hobby: 'JavaScript'}
}
let copyList = Object.assign({}, list);
copyList.obj.hobby = 'Vue'
console.log(list.obj.hobby);    // Vue

2.for in方法

let user1 = {name: "小明",age: 30,height: 1.9,hobby: {project: 'React'}
};
let user2 = {};
for (let i in user1) {user2[i] = user1[i];    //user1[i]输出的是每一个属性的值,将user1的每一个属性的值取出来赋值给user2对象
}
user2.name = '小蓝'
user2.hobby.project = 'Vue'
console.log(user1)      //{ name: "小明", age: 30, height: 1.9, hobby: { project: 'Vue' } }

五、实现深拷贝

1.递归实现

采用递归去拷贝所有层级属性

function deepClone(obj) {let objClone = Array.isArray(obj) ? [] : {};if (obj && typeof obj === "object") {for (key in obj) {if (obj.hasOwnProperty(key)) {//判断ojb子元素是否为对象,如果是,递归复制if (obj[key] && typeof obj[key] === "object") {objClone[key] = deepClone(obj[key]);} else {//如果不是,简单复制objClone[key] = obj[key];}}}}return objClone;
}
let a = [1, 2, 3, 4],b = deepClone(a);
a[0] = 2;
console.log(a, b)   // [2,2,3,4]  [1,2,3,4]

2.JSON.stringify与JSON.parse

通过JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成一个全的新的对象;

let list = [{ name: 'Tom' }];
let copyList = JSON.parse(JSON.stringify([...list]));
copyList[0].name = 'Jerry'
console.log(list[0].name);      // Tom
console.log(copyList[0].name);      // Jerry

3.loadash函数库

函数库lodash,也有提供_.cloneDeep用来做深拷贝

let lodash = require('lodash');
let list = [{ name: 'Tom' }];
let copyList = lodash.cloneDeep(list);
copyList[0].name = 'Jerry'
console.log(list[0].name);      // Tom
console.log(copyList[0].name);      // Jerry

深拷贝、浅拷贝及其实现方式相关推荐

  1. 一篇文章彻底说清JS的深拷贝/浅拷贝

    一篇文章彻底说清JS的深拷贝and浅拷贝 这篇文章的受众 第一类,业务需要,急需知道如何深拷贝JS对象的开发者. 第二类,希望扎实JS基础,将来好去面试官前秀操作的好学者. 写给第一类读者 你只需要一 ...

  2. 对象克隆-深拷贝,浅拷贝,直接赋值

    1背景分析 在 Java 开发中,对象拷贝或者说对象克隆是常有的事,对象克隆最终都离不开直接赋值.浅拷贝.深拷贝 这三种方式,我们常用的对象的转化方式,使用的是spring的 BeanUtils.co ...

  3. java深拷贝和浅拷贝_Java 深拷贝浅拷贝 与 序列化

    一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会 ...

  4. Java基础 深拷贝浅拷贝

    Java基础 深拷贝浅拷贝 非基本数据类型 需要new新空间 class Student implements Cloneable{private int id;private String name ...

  5. 原型模式与深拷贝浅拷贝

    原型模式与深拷贝浅拷贝 原型模式 Java中的原型模式 简单的例子 浅拷贝 深拷贝 效率比较 JMH测试样例 测试结果 原型模式 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或 ...

  6. 超级全面-深拷贝与浅拷贝的实现方式

    一.数据类型: (1)基本数据类型:number,string,Boolean,null,undefined,symbol(ES6),BigInt(ES10): (2)引用数据类型:对象,数组,函数等 ...

  7. Map的putAll方法踩坑实记(对象深拷贝浅拷贝)

    文章目录 问题描述 编写测试代码模拟问题场景 场景1:Map中不包含对象 场景2:Map中包含对象 什么是对象的浅拷贝深拷贝 如何实现深拷贝 问题描述 在一个产品管理系统中,产品信息需要封装一份同步业 ...

  8. JavaScript学习笔记(五)--深拷贝浅拷贝

    如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力. 本篇文章中也会简单阐述到栈堆, ...

  9. java深拷贝的三种方式

    问题:spring boot/JPA项目中,修改某个对象以后需要生成一个VO对象给客户端,数据库对应的POJO对象里有个Map类型的对象(名字叫para),这个对象的value又是个Map,我使用Ma ...

最新文章

  1. Asp.Net MVC 4 Web API 中的安全认证-使用OAuth
  2. 中华成语故事摄制组大公无私的释义
  3. activeMq 安装
  4. IDEA 启动 Tomcat 乱码 解决办法
  5. 计算机机等级考试四级模拟,《全国计算机等级考试上机考试模拟考场-四级》.pdf...
  6. rs232读取智能电表_没想到物联网电表这么智能!插卡预付费电表该升级了!
  7. input数字开头不能为0_李商隐为初恋写诗,每句以数字开头,最后10字一直被仿从未被超越...
  8. 每天五个java相关面试题(3)
  9. android bitmap oom 最新处理办法,【移动开发】Android中图片过大造成内存溢出,OOM(OutOfMemory)异常解决方法...
  10. java shapefile 中文乱码_GeoTools操作Shape格式文件
  11. java的IO操作之--RandomAccessFile
  12. 主数据——共享数据的核心,数据资产的灵魂
  13. Button按钮四种监听(二)及实例
  14. Java实现各种加密验证算法(MD5、SHA256、base64、pdkdf2、pdkdf2_sha256)
  15. 计算机图形学--全局光照(屏幕空间:SSDO,SSR)
  16. 讲座笔记 | 批判性思维和论文写作
  17. 一台 ZXHN F650(GPON ONU) 学习小记
  18. 最通俗易懂的JUC多线程并发编程
  19. 三星会在泰泽大会上展示meego系统的新机么?
  20. YAPI简单使用教程

热门文章

  1. 防夹天窗/ 车窗控制单元
  2. 在读大学生的嵌入式学习指南
  3. 关键词符号:连接关键词用什么符号
  4. PayPal为员工推出区块链创新奖励系统
  5. excel匹配两列数据
  6. Vant 框架 官网中文 api 地址
  7. Android简易音乐重构MVVM Java版-新增推荐、雷达歌单详情列表界面(十八)
  8. speedoffice(Excel)表格如何设置上角标?
  9. python读取CT医学图像
  10. 光流 — Optical Flow