浅拷贝与深拷贝

浅拷贝与深拷贝,第1张

首先我们要知道,js有两大类数据类型:

1.值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol

2.引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。


由于值类型数据较简单,所以创建时候直接储存在栈内存中,在拷贝的时候,会新生成一份储存在栈中,两者互不影响。

而引用数据类型,由于数据结构较复杂,所以创建时候一般都是储存在堆内存中,然后会在栈中生成一份引用(里面保存的是该引用类型在堆内存中的地址,类似c语言的指针)。在拷贝的时候,不会重新在堆内存中生成一份数据,而是直接在栈内存中新生成一份引用指向原本的那个堆内存地址。所以浅拷贝的话,只是拷贝了一份地址,指向了同一个对象,并没有新生成一个对象。


如果我们想要得到原对象的一份真正的独立的复制体,我们就需要对其进行手动深拷贝,即遍历该对象的所有属性,并将其添加到那个复制体对象上面去。

这时候我们会遇到一个问题,如果对象上面的属性是另一个对象,这时候如果我们进行普通普通拷贝,就会遇到和上面同样的问题,所以我们需要对这个手动的深拷贝函数进行循环调用。


function deepClone(obj = {}) {
    if (typeof obj != 'object' || obj == null) {
        //如果传入的obj不是一个对象,那么就不需要进行深拷贝,值类型直接赋值就可以了
        return obj
    }

    //let newObj
    //判断obj是数组还是对象,以确认newObj的类型
    //obj instanceof Object ? newObj = {} : newObj = []

    //优化版
    let newObj = new obj.constructor

    //用for in 遍历obj的属性
    for(let index in obj){
        //只拷贝对象本身拥有的属性,不拷贝原型链上面的属性
        if(obj.hasOwnProperty(index)){
            //循环调用赋值,因为有可能碰到obj的某个属性同样也是一个对象的情况
            newObj[index]=deepClone(obj[index])
        } 
    }
    return newObj
}

 


上面是面试时候一般需要写的深克隆,而实际开发环境中,一般使用

JSON.parse(JSON.stringify(obj))

这种方式的弊端就是无法正确克隆函数、正则、日期等,但是一般开发的话只需要克隆数组、对象、基本值

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/941017.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)

保存