JS实现深度克隆

我们在对数据进行克隆时会遇到两种数据类型,即基本数据类型和引用数据类型.
对于基本数据类型,不需要讨论深度克隆和浅度克隆的问题;而对于引用数据类型,我们需要根据需要对其进行浅克隆(简单的地址引用操作)或深克隆(不只是引用地址的赋值,而是将原本的数据克隆一份,让其不再对原本的数据产生影响).

  1. 浅克隆
    针对数组浅克隆的数据拷贝只是简单的地址引用操作,实现起来比较简单.
    直接赋值:
        var arr1 = [1,2,3,4]
        var arr2 = arr1;
        arr1[0] = 7;
        console.log(arr1); //[7, 2, 3, 4]
        console.log(arr2); //[7, 2, 3, 4]

运用数组的slice方法:

var arr1 = [1,2,3,4]
var arr2 = arr1.slice()
arr1[0] = 7;
console.log(arr1); //[7, 2, 3, 4]
console.log(arr2); //[1, 2, 3, 4]

当数组元素全都是基本类型时此方法适用,但是当数组中包含对象时,此方法失效:

var arr1 = [1,{name:'Jone',age:7},3,4]
var arr2 = arr1.slice()
arr1[1].name = 'Anna';
console.log(arr1); //[1,{name:'Anna',age:7},3,4]
console.log(arr2); //[1,{name:'Anna',age:7},3,4]
  1. 深克隆
    这里提供一种利用递归的方法实现对象的深度克隆
Object.prototype.clone = function(deep){
    // 判断调用克隆这个函数的是什么类型
    // 判断是否是数组
    if(Array.isArray(this)){
        // 判断是否深度克隆
        if(deep){
            var arr = [];
            for(var i = 0; i < this.length; i++){
                arr.push(this[i].clone(true));
            }
            return arr;
        }else{
            // 浅克隆直接截取全部复制返回
            return this.slice;
        }
        
    }else if(Object.prototype.toString.call(this) === '[object Object]'){
        // 判断是否是对象
        var obj = {};
        for(var key in this){
            // 判断是否深度克隆
            if(this.hasOwnProperty(key)){
                if(deep){
                    obj[key] = this[key].clone(true)
                }else{
                    // 浅克隆直接赋值
                    obj[key] = this[key];
                }
            }
        }
        return obj;
    }else{
        return this;
    }
}

验证一下:

        var obj1 = {
            name:'zhangsan',
            age:18,
            obj:{hobby:'sleep',food:'cake'}
        }
        var obj2 = obj1.clone(true);
        obj1['obj'].hobby = 'fishing'
        console.log(obj1);
        console.log(obj2);
上一篇:IAsyncEnumerable with yield in C#


下一篇:2021-09-25