手写深浅拷贝

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

前言: 记得是在《你不知道的JavaScript》书上恰好看到了一个深浅拷贝的概念,当时最开始看到这个概念的时候感觉挺新奇的,拷贝就拷贝,怎么还有深浅呢?于是昨天就浅浅的深入学习了一下,就又开启了一段秃头之旅qwq…

什么是浅拷贝?

对于浅拷贝来说,拷贝出来的新对象里面的值会随着旧对象里面值的改变而改变,也就是说这种拷贝方式是将旧对象某个值的引用地址拷贝给新对象,新旧对象的值访问的都是这个引用地址。

什么是深拷贝?

对于深拷贝来说,这种拷贝方式会生成两个一模一样的两个对象,并且这两个对象更改自己的值不会影响另外一个对象里面的值;也就是说这种拷贝方式是将原对象的 值 拷贝了一份,是生成了一个值,而不是引用该值。

哪些方法可以实现深浅拷贝?

浅拷贝

  1. 可以使用 Object.assign() 来实现浅拷贝,这个函数会将所有的属性拷贝到新的对象里面,当然如果这个属性是对象的话,拷贝的是这个对象的引用地址。
// 拷贝的是原始值类型
 let a={  
    name:'bruce'
}

let b=Object.assign({},a)
console.log(b.name);   // bruce
a.name="lucy"
console.log(a.name);   // lucy
console.log(b.name);   // bruce

// 拷贝引用类型

let a={
    people:{
        name:'bruce'
    }
}
let b=Object.assign({},a)

b.people.name="lucy"
console.log(a.people);  // { name: 'lucy' }
console.log(b.people);  // { name: 'lucy' }

2.通过解构实现浅拷贝

let a={
    name:'bruce'
}

let b={...a}
console.log(b);  //{ name: 'bruce' }

深拷贝

实现深拷贝可以使用 JSON.parse(JSON.stringify(object)) 这个方法可以实现深拷贝的效果,当然这个方法也存在一些缺点。

let a={
    name:'bruce',
    like:{
        name:'running'
    }
}

let b=JSON.parse(JSON.stringify(a))
console.log(b); 

如果对象里面存在值的循环引用会报错


let obj1={
    a:1,
    b:2,
    c:{
        d:4,
        e:5,
    }
}

obj1.a=obj1.c
obj1.b=obj1.c.d
obj1.c.d=obj1.a

let obj2=JSON.parse(JSON.stringify(obj1))
console.log(obj2);

对象中值循环引用

QQ图片20221130231638.png

当然这个方法也不接受函数、undefined、symbol这三种数据类型的拷贝。

好了现在大家对深浅拷贝的概念以及实现方法有了一定的了解,下面我们就来用代码实现一下深浅拷贝。

手写浅拷贝

首先要实现一个浅拷贝,其基本原理如下:

  1. 判断拷贝的对象是否为基本类型(基本类型就不需要进行像拷贝引用类型引用的操作)
  2. 排除了要拷贝的对象不是基本类型后判断这个对象是对象还是数组(这决定最后返回的是对象还是数组)
  3. 再遍历这个对象的属性将属性拷贝给新对象
let a={
    name:'bruce'
}

function shallowCopy(oldObj){
    if(typeof oldObj !=='object') return  oldObj// 如果是基本类型就直接返回这个值

    let newObj=oldObj instanceof Array ? []:{}  // 判断是对象还是数组
    for(let key in oldObj){   // 遍历对象上面的属性
        if(oldObj.hasOwnProperty(key)){  
            newObj[key]=oldObj[key]
        }
    }
    return newObj
}

console.log(shallowCopy(a)); // { name: 'bruce' }

手写深拷贝

上面实现了浅拷贝,深拷贝与其非常相似,就只有一点要考虑,如何解决拷贝的对象里面嵌套的一个又一个对象?
其实拷贝每一层对象都是一样的,都是由一次浅拷贝,我们只要在拷贝的时候去判断当前拷贝的是一个对象还是一个基本类型,如果是一个对象就递归的调用拷贝方法。

let a={
    name:'bruce',
    like:{
        name:'running'
    }
}
let c=1

function deepCopy(oldObj){
    if(typeof oldObj !=='object') return oldObj

    let newObj=oldObj instanceof Array ? []:{}
    for(let key in oldObj){
        if(oldObj.hasOwnProperty(key)){
            if(typeof oldObj[key]==='object'){  // 判断这个值是否为对象
                deepCopy(oldObj[key])  // 是的话就递归的调用这个方法
            }
            newObj[key]=oldObj[key]
        }
    }
    return newObj
}

console.log(deepCopy(a)); //{ name: 'bruce', like: { name: 'running' } }

这就实现了一个深拷贝。

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容