zoukankan      html  css  js  c++  java
  • 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对象拷贝,已经足够
  • 相关阅读:
    JZOJ 3034. 【NOIP2012模拟10.17】独立集
    JZOJ 3035. 【NOIP2012模拟10.17】铁轨
    JZOJ 1259. 牛棚安排
    数位DP JZOJ 3316. 非回文数字
    JZOJ 3046. 游戏
    JZOJ 3013. 填充棋盘
    debian 安装oracle提供的java8
    java 汉字转拼音 PinYin4j
    debian ssh设置root权限登陆 Permission denied, please try again
    java并发下订单生成策略
  • 原文地址:https://www.cnblogs.com/sefaultment/p/9446174.html
Copyright © 2011-2022 走看看