详解深拷贝,浅拷贝

目的:深拷贝希望赋值后的变量的变化不会影响到原来的变量

基础知识要求:

数据类型

基本数据类型:number,string ,boolean,null,undefined,bigInt,symbol
复杂(引用、Object类型)数据类型:object,arry,date,function,regexp
基本数据类型存储在栈中,复杂数据类型存储在堆中,在栈中只保留复杂数据类型的属性和引用地址

判断数据类型的方法

  • typeof
    • 使用方法:
      • typeof 10 //‘Number’
      • typeof {}//‘Object’
      • typeof null//‘Object’
        在这里插入图片描述
    • 缺点:typeof null的值为object,无法分辨是null还是object
  • instanceof
    • 使用方法:
      • function instanceof func;//true
      • 123 instanceof Number;//false;
    • 缺点:只能判断对象是否存在目标对象的原型链上,不能判断字面量的基本数据类型

原型链中的任何属性都会产生值,如何处理到不需要的属性

  • 让你的程序做检查,并丢弃值为函数的属性
  • 使用hasOwnProperty方法。如果对象拥有独有的属性,它将会返回true。hasOwnProperty方法不会检查原型链()。

浅拷贝:复杂数据类型的存在赋值关系的两个变量指向同一个引用地址
深拷贝:旧对象指向原来的引用地址,新对象在堆中创建一个新的空间,指向新的引用地址
浅拷贝原理:

参考B站up“前端小野森森-2”

浅拷贝方式1
const oldObj={
    name:'哈默',
    age:20,
    colors:['orange','green','blue'],
    friend:{
        name:'小夏'
    },
}
const newObj=oldObj;
newObj.name='小野';
console.log('oldObj',oldObj);
console.log('newObj',newObj);

解析:oldObj.name和newObj.name的值是一样的,因为是浅拷贝,我们改变了对象的一个值,另一个对象对应的值也会跟着改变;
当我们不希望出现同步改变的时候,就会用到深拷贝;
即newObj的值发生改变时,oldObj的值不会改变

const oldObj={
    name:'哈默',
    age:20,
    colors:['orange','green','blue'],
    friend:{
        name:'小夏'
    },
}
function deepClone(obj){
    if( typeof obj !=='object'||obj == null){
        return obj;}
    let result;
    if(obj instanceof Array){
        result= [];
    }else{
        result={};
    };
    for(let key in obj){
        result[key]=obj[key]
    };
    return result;
}
const newObj=deepClone(oldObj);
newObj.name='小野';
console.log('oldObj',oldObj);
console.log('newObj',newObj);

但是这种方式的深拷贝,只拷贝了一层,它不会去处理嵌套的对象,如oldObj.friend.name的值
所以我们不能直接赋值,应该在函数里面应该递归的调用函数本身;完成嵌套对象的值的深拷贝

for(let key in obj){
    result[key]=deepClone(obj[key])
}

还有一个优化点是,应该只拷贝原来对象上自身的属性,原来对象原型上的属性不应该拷贝

for(let key in obj){
    if(obj.hasOwnProperty(key)){
        result[key]=deepClone(obj[key])
    }
}

遗留点: 没有讲循环引用问题
循环引用解决思路:添加一个参数cache,里面存储处理过的参数,当遇到循环引用时,将cache中存储的信息返回即可

参考B站up“左耳击水兽”

1、JSON.parse(JSON.stringify())

  • 优点:二层及以上可以实现深拷贝
  • 缺点
    • 无法拷贝函数
    • 无法拷贝正则
    • 无法拷贝undefined

2、借助第三方库lodash实现深拷贝

浅拷贝方式2
var shallowObj2 = { ...obj1 }
浅拷贝实现方式3

2、Object.assign()

  • 优点
    • 可以拷贝函数
    • 可以拷贝正则
    • 可以拷贝undefined
  • 缺点 :二层及以上无法实现深拷贝

参考:

  • 书籍《JavaScript 语言精粹(修订版)》
  • CSDN平台博主“晟小明”<身为三本的我就是凭借这些前端面试题拿到百度京东offer的,前端面试题2021及答案>
  • B站up“前端小野森森-2”
  • B站up“左耳击水兽”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值