深浅拷贝区别 以及手写深拷贝

本文介绍了JavaScript中的浅拷贝与深拷贝概念,浅拷贝包括Object.assign和数组的方法如concat和slice,它们都进行表面拷贝。而深拷贝可以通过JSON.parse(JSON.stringify())实现,但有性能和特殊类型的限制。另外,文中还提供了一个手写深拷贝函数的示例,并提到了lodash库的_.cloneDeep方法作为深拷贝的工具。
摘要由CSDN通过智能技术生成

一、概念

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

二、浅拷贝的实现方式

  1. Object.assign()
    Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
    在这里插入图片描述
    注意:当object只有一层的时候,是深拷贝
    在这里插入图片描述

  2. Array.prototype.concat()
    在这里插入图片描述
    修改新对象会改到原对象:
    在这里插入图片描述

  3. Array.prototype.slice()
    在这里插入图片描述
    修改新对象会改到原对象:
    在这里插入图片描述

三、深拷贝的实现方式

  1. JSON.parse(JSON.stringify())
let arr = [1, 3, {username: 'kobe'}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'libai';
console.log(arr, arr4)

在这里插入图片描述
原理:用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

弊端:
(1)序列化反序列化十分耗性能;
(2)如果遇到key是js函数或者js关键字,会自动跳过。

  1. 手写深拷贝
function deepClone(sourceObj){
   //建立新容器
   const targetObj = sourceObj.constructor === Array ? [] : {}
   // 遍历
   for(let keys in sourceObj){
     if(sourceObj.hasOwnProperty(keys)){
         // 判断是基础数据类型还是引用数据类型,如果是引用数据类型
         if(targetObj[keys] && typeof sourceObj[keys] === 'Object'){
             targetObj[keys] = sourceObj[keys].constructor === Array ? [] : {}
             targetObj[keys] = deepClone(sourcrObj[keys])
         } else {
             // 基本数据类型
             targetObj[keys] = sourceObj[keys]
         }
      }
   }
   return targetObj
}
let sourceObj = {
    num: 12,
    str: 'xxx',
    bol: false,
    // 函数的处理一般只是功能的复用
    fn: function(){console.log('6')},
    // 也不需要处理
    nulVal: null,
    // 无元素,可以直接通过构造函数new出来的
    reg: /7/,
    date: new Date(),
    // 新结构
    map: new Map([['d', 8], ['c', 4]]),
    set: new Set([10, 11]),
    //[key+value]
    array: [1,2],
    arrayofobj: [{a: 3, b: 4}],
    obj: {c: 5} 
}

在这里插入图片描述

  1. 函数库lodash
    该函数库也有提供_.cloneDeep用来做 Deep Copy
var _ = require('lodash');
var obj = {
   a: 1,
   b: {f: {g: 1}},
   c: [1, 2, 3]
}
var obj2 = _.cloneDeep(obj);
console.log(obj.b.f == obj2.b.f)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深拷贝浅拷贝JavaScript 中用于复制对象的两种不同方式。 浅拷贝只是复制对象的第一层属性,而不会复制对象中的引用类型属性。也就是说,浅拷贝只会复制对象的引用,而不会创建一个新的对象。这意味着,如果原始对象中的引用类型属性发生变化,拷贝后的对象中的属性值也会随之改变。使用浅拷贝可以通过遍历对象中的属性,并将其复制到一个新对象中来实现。你可以使用循环、递归或者使用一些内置的方法来手写浅拷贝。举个例子,你可以通过遍历对象中的属性,并将其复制到一个新对象中来实现浅拷贝。比如使用递归的方式,你可以逐个复制对象中的属性到一个新的对象中,但是注意,只有第一层的属性会被复制到新对象中。 深拷贝则是复制对象的所有层次,包括对象的引用类型属性。这意味着,如果原始对象中的引用类型属性发生变化,拷贝后的对象中的属性值不会受影响。深拷贝会创建一个完全相同但是独立的对象。实现深拷贝可以使用递归的方式,对于对象的每一个属性,如果是引用类型,则递归调用深拷贝方法来复制属性值。你也可以使用一些内置的方法或者第三方库来实现深拷贝,比如使用 JSON.parse(JSON.stringify(object)) 来实现深拷贝需要注意的是,使用这种方法时,对象中的函数、正则表达式以及 undefined 类型的属性会被忽略掉。 所以,通过手写深拷贝浅拷贝,可以更好地理解递归、循环引用、weakMap、创建各种引用类型的方法、判断数据类型、箭头函数与普通函数的区别、正则表达式等知识。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JavaScript基础:手写浅拷贝深拷贝](https://blog.csdn.net/imagine_tion/article/details/115322522)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JS 浅拷贝深拷贝详解(巨详细)](https://blog.csdn.net/qq_63299825/article/details/131003216)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值