实现一个深浅拷贝

一、直接赋值

直接赋值将会改变基本数据类型和引用数据类型

const a = {
    "name":'wyy',
    source:[100,99,98],
    hobby:"reading"
}
// 将b直接赋值给a
const b = a
b.source = [1, 2, 3]
console.log(a); //{ name: 'wyy', source: [ 1, 2, 3 ], hobby: 'reading' }
console.log(b); //{ name: 'wyy', source: [ 1, 2, 3 ], hobby: 'reading' }

二、浅拷贝的原理和实现

“自己创建一个新对象,来接收你重新复制或引用新对象的值。如果对象的属性是基本数据类型,复制的值就是基本数据类型的值给新对象;但如果属性的值是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存地址中的内容,另外一个对象肯定也受影响”

1. 实现浅拷贝的四种方法

  • object.assign()
const a = {
    'aaa':{
        val:'1',
        child:{
            val:'little'
        }
    },
    name:'bob'
}
const b = Object.assign({age:18},a)
b.name ='Alice'
b.aaa.val = '2'
// { age: 18, aaa: { val: '2', child: { val: 'little' } }, name: 'Alice' }
console.log(b);
// { aaa: { val: '2', child: { val: 'little' } }, name: 'bob' }
console.log(a);
  • 扩展运算符

扩展运算符类似于object.assign

const a = {
    'aaa':{
        val:'1',
        child:{
            val:'little'
        }
    },
    name:'bob',
    symbpl: Symbol('n')
}
const b = {...a}
b.name ='Alice'
b.aaa.val = '2'
console.log(b);
console.log(a);
  • concat拷贝数组,该方法仅用来实现数组的浅拷贝
const a = [1,2,3,4,5]
const b = a.concat()
// [ 1, 2, 3, 4, 1, 2, 3, 4, 5]
console.log(b);
// [ 1, 2, 3, 4, 5 ]
console.log(a);
  • slice拷贝数组
const a = [1,2,3,4,5]
const b = a.slice(1,3)
// 返回一个新的数组
// [ 2, 3 ]
console.log(b);
// [ 1, 2, 3, 4, 5 ]
console.log(a);

2. 手写实现浅拷贝

思路:

  • 对基本类型做一个最基本的copy
  • 对引用类型开辟新的存储空间
const shallowCopy = (target)=>{
    if(typeof target === 'object'&& target !== null){
        const cloneTarget = target.isArray()?[]:{}
        for(let prop in target){
            if(target.hasPrototype(prop)){
                cloneTarget[prop] = target[prop]
            }
        }
        return cloneTarget
    }else{
        return target
    }

}

3. 浅拷贝特性

  • 不会拷贝对象的继承属性
  • 不能实现嵌套拷贝
  • 可以拷贝symbol类型的属性

三、深拷贝的原理以及实现

“将一个对象从内存中完整地拷贝出来一份给目标对象,并从堆内存中开辟一个全新的空间存放新对象,且新对象的修改并不会改变原对象,二者实现真正的分离”

  • json.stringfy()(乞丐版,存在较多问题)

1.拷贝date会变成字符串

2.键值对消失,拷贝函数,undifined,symbol时

3.无法拷贝原型链

4.无法拷贝循环引用

5.无法拷贝不可枚举类型

6.拷贝正则会变成空对象

  • 递归实现深拷贝

思路:
1. 针对能够遍历对象的不可枚举类型属性以及symbol类型,使用Reflect.ownKeys方法。

2. 当参数为Date.RegExp类型,则直接生成一个新的实例返回。

3.利用object的getOwnPropertyDescriptors方法可以获得对象的所有属性,以及对应的特性,顺便结合Object的create方法创建一个新对象,并继承传入原对象的原型链。

4.利用WeakMap类型作为Hash表,因为WeakMap是引用类型,可以有效防止内存泄漏,作为检测循环引用很有帮助,如果存在循环,则引用直接返回WeakMap存储的值。

未实现手写深拷贝

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值