• JS中的浅拷贝与深拷贝


    浅拷贝与深拷贝的区别:

    浅拷贝:
        对基本类型和引用类型只进行值的拷贝,即,拷贝引用对象的时候,只对引用对象的内存地址拷贝,新旧引用属性指向同一个对象,修改任意一个都会影响所有引用当前对象的变量。
    
    深拷贝:
        对引用类型所引用的对象也进行拷贝。使得新旧引用属性指向不同的对象,达到两者状态分离的效果。
    

    实现方案:

    方案一:
    Object.assign()方法可以用于合并对象,并且只在顶层属性上进行合并。

    var obj1 = { x: 1, y: 2 },
        obj2 = Object.assign({}, obj1);
    console.log(obj1); //{x: 1, y: 2}
    console.log(obj2); //{x: 1, y: 2}
    obj2.x = 2; //修改obj2.x
    console.log(obj1); //{x: 1, y: 2}
    console.log(obj2); //{x: 2, y: 2}
    

    缺点:只实现了合并时顶层这一层的深拷贝。

    方案二:
    JSON.parse(JSON.stringify(obj))利用 JSON 对象中转一次,实现深拷贝。

    var obj1 = {
        x: 1,
        y: {
            m: 1
        }
    };
    var obj2 = JSON.parse(JSON.stringify(obj1));
    console.log(obj1); //{x: 1, y: {m: 1}}
    console.log(obj2); //{x: 1, y: {m: 1}}
    obj2.y.m = 2; //修改obj2.y.m
    console.log(obj1); //{x: 1, y: {m: 1}}
    console.log(obj2); //{x: 2, y: {m: 2}}
    

    缺点:由于 JSON 对象转化规则,undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)且只适用于能够用 JSON 表示的对象。

    例子:

    var obj1 = {
        x: 1,
        y: undefined,
        z: function add(z1, z2) {
            return z1 + z2;
        },
        a: Symbol("foo")
    };
    var obj2 = JSON.parse(JSON.stringify(obj1));
    console.log(obj1); //{x: 1, y: undefined, z: ƒ, a: Symbol(foo)}
    console.log(JSON.stringify(obj1)); //{"x":1}
    console.log(obj2); //{x: 1}
    

    方案三:
    使用 for in 遍历原型以及自身所有可枚举属性,在遇到 object 时递归自身完成对象深拷贝。

    var deepClone = function fnDeepClone(obj) {
        var result = typeof obj.splice === "function" ? [] : {},
            key;
        if (obj && typeof obj === "object") {
            for (key in obj) {
                if (obj[key] && typeof obj[key] === "object") {
                    result[key] = fnDeepClone(obj[key]); //如果对象的属性值为object的时候,递归调用deepClone,即再把某个值对象复制一份到新的对象的对应值中
                } else {
                    result[key] = obj[key]; //如果对象的属性值不为object的时候,直接复制参数对象的每一个键/值到新对象对应的键/值中
                }
            }
            return result;
        }
        return obj;
    };
    
    var obj1 = {
        family: { brother: "wangzhipeng", father: "wanglicai", mother: "sunaiyun" },
        name: "gino",
        sex: "male",
        age: "27",
        test: undefined,
        a: Symbol("foo"),
        f() {}
    };
    var obj2 = deepClone(obj1);
    obj1.sex = "close";
    obj2.age = "33";
    obj1.f = () => {
        console.log(1111);
    };
    console.log(obj1);
    console.log(obj2);
    

    缺点:只支持object和array类型

    方案四:
    使用 Object.create 以 obj 原型创建一个对象,然后使用 Objcet.getOwnPropertyDescriptors 获取对象属性描述符数组来创建这个对象。

    var deepClone = function(o) {
        var copy = Object.create(
            Object.getPrototypeOf(o),
            Object.getOwnPropertyDescriptors(o)
        );
        return copy;
    };
    
    var obj1 = {
        family: { brother: "wangzhipeng", father: "wanglicai", mother: "sunaiyun" },
        name: "gino",
        sex: "male",
        age: "27"
        f(){
    
        }
    };
    var obj2 = deepClone(obj1);
    obj1.sex = "close";
    obj2.age = "33";
    console.log(obj1);
    console.log(obj2);
    

    优点:在对象属性中允许函数、undefined、Symbol 拷贝,还能继承原型

    总结:

    以上方法暂未实现包装对象,Date对象,正则对象的深拷贝,尚未验证DOM对象深拷贝后功能函数是否正常,对于后台JSON对象拷贝,已经足够
  • 相关阅读:
    luogu P3368 【模板】树状数组 2
    dp
    vijos 羽毛
    luogu tyvj 纪念品分组
    codevs 1259 最大正方形子矩阵 WD
    python 序列化之pickle模块 json模块
    python 类的进阶
    python 面向对象与类的基本知识
    python 异常处理
    python time模块 sys模块 collections模块 random模块 os模块 序列化 datetime模块
  • 原文地址:https://www.cnblogs.com/sefaultment/p/9446174.html
Copyright © 2020-2023  润新知