首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

什么是深拷贝;深拷贝和浅拷贝有什么区别;深拷贝和浅拷贝有哪些方法(详解)

  • 25-02-22 02:41
  • 2468
  • 6962
blog.csdn.net

目录

一、为什么要区别深拷贝和浅拷贝

二、浅拷贝

2.1、什么是浅拷贝

2.2、浅拷贝的方法

使用Object.assign()

使用展开运算符(...)

使用数组的slice()方法(仅适用于数组)

2.3、关于赋值运算符(=)

三、深拷贝

3.1、什么是深拷贝

3.2、实现深拷贝的三种常见方法

使用JSON.parse(JSON.stringify(obj))

使用第三方库,如lodash的cloneDeep()

手动实现递归函数

四、总结


一、为什么要区别深拷贝和浅拷贝

        在JavaScript中,对象和数组是引用类型,这意味着当你将它们赋值给一个变量或者作为函数参数传递时,你实际上是在传递一个指向内存中对象的引用,而不是对象本身的副本。这就涉及到了深拷贝和浅拷贝的概念。

二、浅拷贝

2.1、什么是浅拷贝

        浅拷贝只复制对象的第一层属性。也就是说,如果原始对象的属性是基本类型(如数字、字符串、布尔值),那么浅拷贝会复制这些值;但如果属性是引用类型(如数组、对象、函数),那么拷贝的只是引用,而不复制引用指向的内存地址中的数据。

2.2、浅拷贝的方法

使用Object.assign()
  1. let original = { a: 1, b: { c: 2 } };
  2. let shallowCopy = Object.assign({}, original);
  3. original.a = 3;
  4. original.b.c = 4;
  5. console.log(shallowCopy.a) // 1 ; original.a是original的第一层属性,值是一个数字,所以浅拷贝到shallowCopy中还是一个数值,不受original影响
  6. console.log(shallowCopy.b.c) // 4 ; original.b.c是original的第二层属性,第一层属性original.b的值是一个引用类型,浅拷贝只会拷贝引用,所以修改original.b.c也会修改shallowCopy.b.c
使用展开运算符(...)
  1. let original = { a: 1, b: { c: 2 } };
  2. let shallowCopy = { ...original }; // 使用展开运算符进行浅拷贝
  3. original.a = 3;
  4. original.b.c = 4;
  5. console.log(shallowCopy.a) // 1 ; original.a是original的第一层属性,值是一个数字,所以浅拷贝到shallowCopy中还是一个数值,不受original影响
  6. console.log(shallowCopy.b.c) // 4 ; original.b.c是original的第二层属性,第一层属性original.b的值是一个引用类型,浅拷贝只会拷贝引用,所以修改original.b.c也会修改shallowCopy.b.c
使用数组的slice()方法(仅适用于数组)
  1. let originalArray = [1, 2, 3, [4, 5]];
  2. let shallowCopyArray = originalArray.slice();
  3. originArray.push(6);
  4. originArray[3].push(5);
  5. console.log(originalArray); // 输出: [1, 2, 3, [4, 5, 5], 6]
  6. console.log(shallowCopyArray); // 输出: [1, 2, 3, [4, 5, 5]]
  7. let originalArray = [1, 2, 3, [4, 5]];
  8. let shallowCopyArray = originalArray.slice();
  9. originArray.push(6);
  10. originArray[3].push(5);
  11. originArray[3] = [4, 5];
  12. console.log(originalArray); // 输出: [1, 2, 3, [4, 5], 6]
  13. console.log(shallowCopyArray); // 输出: [1, 2, 3, [4, 5, 5]] 因为 [4, 5]是一个新数组,是将新的引用赋给了originArray[3],并不会直接改变shallowCopyArray[3]的引用

2.3、关于赋值运算符(=)

        在JavaScript中,赋值运算符(=)本身并不执行浅拷贝或深拷贝。赋值运算符只是将一个值或一个引用赋给一个变量。如果赋值的是一个基本数据类型(如数字、字符串、布尔值),那么赋值运算符会复制这个值。如果赋值的是一个引用类型(如对象、数组、函数),那么赋值运算符会复制这个引用,而不是引用指向的对象本身。

        当使用赋值运算符来处理对象和数组时,没有创建一个新的对象/数组,两个变量指向的是同一个对象/数组,所以不管修改哪一个对象/数组的任何一层的任何一个数据,另外一个都会随之改变。(连浅层/第一层的数值都没有拷贝,完全依赖引用)

  1. let a = 10; // a是基本数据类型
  2. let b = a; // b复制了a的值,a和b现在是两个独立的数字
  3. console.log(a === b); // true,因为它们都是数字10
  4. let obj1 = { key: 'value' };
  5. let obj2 = obj1; // obj2复制了obj1的引用
  6. obj2.key = 'new value'; // 修改obj2的key属性
  7. console.log(obj1.key); // 输出 'new value',因为obj1和obj2引用的是同一个对象
  8. console.log(obj1 === obj2); // true,因为它们引用的是同一个对象
  9. let obj3 = { key: 'value' , deep:{a:5 , b:6}};
  10. let obj4 = obj1; // obj2复制了obj1的引用
  11. obj3.deep.a = 6
  12. console.log(obj4.deep.a); //6

三、深拷贝

3.1、什么是深拷贝

        深拷贝会创建一个全新的对象,并且递归地复制所有属性,使得原始对象和拷贝对象完全独立,互不影响。深拷贝后的对象中所有的属性都是新的引用,即使属性是引用类型,也会被完全复制。

        实现深拷贝的方法相对复杂,因为需要递归地复制对象的所有层级。以下是一些常见的实现方式

3.2、实现深拷贝的三种常见方法

使用JSON.parse(JSON.stringify(obj))

        这是最简单的一个方法,实际开发中经常会用到,不过虽然简单但有局限性,不能处理函数、undefined、循环引用、特殊对象(如Date、RegExp)等。

  1. let original = { a: 1, b: { c: 2 } };
  2. let deepCopy = JSON.parse(JSON.stringify(original));
使用第三方库,如lodash的cloneDeep()
  1. let original = { a: 1, b: { c: 2 } };
  2. let deepCopy = JSON.parse(JSON.stringify(original));
手动实现递归函数

        实现深拷贝的递归函数需要考虑多种情况,包括但不限于:

  • 检测对象是否为基本类型。
  • 处理循环引用。
  • 复制数组和对象。
  • 处理特殊对象(如Date、RegExp)。

        举个例子:

  1. function deepCopy(obj, hash = new WeakMap()) {
  2. if (obj === null) return null;
  3. if (typeof obj !== 'object') return obj;
  4. if (obj instanceof Date) return new Date(obj);
  5. if (obj instanceof RegExp) return new RegExp(obj);
  6. if (hash.has(obj)) return hash.get(obj);
  7. let result;
  8. if (Array.isArray(obj)) {
  9. result = [];
  10. hash.set(obj, result);
  11. for (let i = 0; i < obj.length; i++) {
  12. result[i] = deepCopy(obj[i], hash);
  13. }
  14. } else {
  15. result = Object.create(Object.getPrototypeOf(obj));
  16. hash.set(obj, result);
  17. for (let key in obj) {
  18. if (obj.hasOwnProperty(key)) {
  19. result[key] = deepCopy(obj[key], hash);
  20. }
  21. }
  22. }
  23. return result;
  24. }

四、总结

        浅拷贝适用于只复制对象的第一层属性,且这些属性不是引用类型。深拷贝适用于需要完全独立的副本,包括对象和数组的嵌套结构。选择哪种拷贝方式取决于你的具体需求和场景。

        意犹未尽?更多精彩前端好文请关注:各种前端问题的技巧和解决方案

        博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览62647 人正在系统学习中
注:本文转载自blog.csdn.net的Watermelo617的文章"https://blog.csdn.net/RenGJ010617/article/details/139704285"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top