浅克隆与深克隆

238 阅读3分钟

克隆

基础数据类型与栈内存

基础数据类型又叫做原始数据类型,有Number String Boolean Null Undefine Symbol(ES6新增)。

在计算机中声明这些数据是要占用内存的,存在即占用空间,这个空间就是栈内存。

打个比方,一本书有目录,然后目录记录具体的页码,这里的栈内存就相当于目录。

引用数据类型与堆内存

引用数据类型有Object Array Function

在计算机中声明这类数据也是要占用内存的,并且占用两种内存,堆内存和栈内存。

在栈内存中,存储着数据的指针,这个指针对应着堆内存的具体位置,而数据的具体位置就是存储在堆内存中。

打个比方,还是一本书,目录对应栈内存,具体每页则对应堆内存。

浅克隆

所以浅克隆的意思就是,同一本书,只克隆了目录,两个目录同时对应一本书,即多对一。

如果按照其中1个目录去修改书的内容,那么另一个目录所对应的内容也会随之改变,因为只有一本书。

实现浅克隆

     function qianClone(old){
            const newObj = {};
            for(var key in old){
                newObj[key] = old[key]
            }
            return newObj;
        }
    const oldObj = {
        a: 1,
        b: ['e', 'f', 'g'],
        c: { h: { i: 2 } }
    }
    var newObj = qianClone(oldObj)
    newObj.b[0] = 'aaaa'
    console.log(newObj.b[0],oldObj.b[0]) //aaaa aaaa
    console.log(oldObj.c.h === newObj.c.h); true

深克隆

那么深克隆就懂了吧,就是完全克隆一本书,目录和内容全部复制一份,变成两本一样,但又互不想干的书。

如果想对其中一本书的内容进行修改,也不会影响另一本书。

实现深克隆

有一种快速实现深克隆的方法,就是将一个对象转为字符窜,然后再将这个字符窜转为对象,这样就可以快速的实现深克隆了。

JSON.Stringify(obj) 可以将JS对象转为字符窜 JSON.parse(string) 可以将字符窜转为对象

var newObj = JSON.parse(JSON.Stringify(oldObj));

这种方法虽然快速,但有很多缺陷,比如:

1、无法对函数、正则等特殊对象进行克隆

2、会抛弃对象的constructor,所有的构造函数会指向Object

3、对象有循环引用,会报错

实现深度克隆2.0版本

  const oldObj = {
            a: 1,
            b: ['e', 'f', 'g'],
            c: { h: { i: 2 } }
        };
    function deepClone(origin,target){
        var target = target || {},
            toStr = Object.prototype.toString,
            arrStr = "[object Array]";
        for(var prop in origin){
            if(origin.hasOwnProperty(prop)){
                if(typeof(origin[prop]) == 'object'){
                    if(toStr.call(origin[prop]) == arrStr){
                        target[prop] = []
                    }else{
                        target[prop] = {}
                    }
                    deepClone(origin[prop],target[prop])
                }else{
                    target[prop] = origin[prop]
                }
            }
        }
        return target;
    }
    var newObj = deepClone(oldObj);

这个深度克隆主要简单实现了数组和对象的克隆。

深度克隆实现是建立在浅克隆的基础之上的,主要思想如下。

1、for循环、判断是引用类型还是原始类型

2、原始类型就直接浅克隆,引用类型再继续判断是数组还是对象

3、对引用类型进行递归,直到数据为原始类型,此时跳出递归并且进行了浅克隆

4、至此,在浅克隆与递归算法的基础上实现了深克隆