什么是深拷贝?什么是浅拷贝?如何实现深拷贝?

在了解浅拷贝和深拷贝之前,我们先了解一下js的数据类型
js的数据类型分为两种
一种是基本数据类型:字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)
一种是引用数据类型:对象(Object)、数组(Array)、函数(Function)
基本类型的变量是存放在栈内存,引用数据类型是放在堆内存中的,基本数据类型保存的是值,而引用数据类型一般保存的是对象的地址。
如果我们单纯的复制的话,可能就只是复制对象的地址,那么这就是浅拷贝,如果是克隆了对象,改变了引用对象的地址,那么就是深拷贝。

浅拷贝就是拷贝指向对象的指针
深拷贝就是克隆了对象,并重新在堆中指向了一个新的地址
只有引用数据类型才存在浅拷贝和深拷贝,基本数据类型就是赋值

上面用文字说了那么多可能还是很懵
那么举个例子吧

//浅拷贝
let obj1 = {a:1,b:{c:1}}
let obj2 = {...obj1} 
obj1.b === obj2.b  // 值为true,说明对象 obj1 的子对象 b 和 对象 obj2 的子对象指向同一个地址
//深拷贝
let obj1 = {a:1,b:{c:1}}
let obj3 = {..obj1,b:{...obj1.b}}
obj3.b === obj1.b // 值为false,说明对象 obj1 的子对象 b 和 对象 obj3 的子对象在堆内存中指向不同的地址

简而化之:
浅拷贝和深拷贝的区别是:看复制的子对象是否在堆内存中指向一个新的地址

那么怎么实现一个深拷贝呢?
实现思路:

  1. 检查类型,判断类型是否为引用类型,是就进行深拷贝,否则浅拷贝
  2. 使用递归
  3. 检查环,判断当前引用是否指向自身,避免进入死循环
  4. 需要忽略原型

简易版实现代码(只处理了Object和Array两种引用类型):

function deepClone(obj){
  // 判断当前对象是对象还是数组
  let result = Array.isArray(obj)?[]:{};
  if(obj && typeof obj === "object"){
    for(let key in obj){
       // 判断是否为自身属性
      if(obj.hasOwnProperty(key)){
        if(obj[key] && typeof obj[key] === "object"){
          //子元素为对象,进入递归
          result[key] = deepClone(obj[key]);
        }else{
          result[key] = obj[key];
        }
      }
    }
  }
  return result;
}

快捷深拷贝的方法

  1. 通过序列化和反序列化得到一个新的对象,JSON.parse(JSON.stringify(a));缺点:会忽略 Function、Symbol、undefined,造成属性丢失,如果在知道深拷贝对象的类型中不含有这些类型的话,这个方法还是相当的好用。
  2. 第三方工具:jquery 提供一个$.extend可以用来做深拷贝,lodash函数库提供的_.cloneDeep也可以用来做深拷贝
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值