zoukankan      html  css  js  c++  java
  • 深入浅出:了解深拷贝和浅拷贝

    值传递:基本数据类型传递数据(数据发生改变的时候,另一个数据不会发生改变)
    引用传递:引用数据类型传递数据,复制另一个引用数据类型的地址,所以当数据发生改变的时候,另一个引用数据类型的数据也会发生改变。因为他们的两个只想同一地址。
     1.浅拷贝:当一个对象复制另一个对象的数据后,当改变其中一个对象的数据后,另一个对象的数据也会发生改变,这就是浅拷贝;
     2.深拷贝:当一个对象复制另一个对象的数据后,当改变其中一个对象的数据后,另一个对象的数据不会发生改变,这就是深拷贝;
     (1).最简单的浅拷贝
    var obj = { a: 1, b: 2, c: 3 };
    var newObj = obj;
    newObj.a = 10;
    console.log(obj);//{a:10,b:2,c:3}
    console.log(newObj);//{a:10,b:2,c:3};

    (2).ES6对象的方法:Object.assign():第一个参数是目标对象,后面的参数都是源对象(需要拷贝的对象);返回值是合并后的对象。
    例:当对象是多层的时候
    var obj = { data: { a: 1, b: 2, c: 3 } };
    var newObj = Object.assign({}, obj);
    newObj.data.a = 10;
    console.log(obj, newObj)
    3、自己封装copy的方法
    var obj = {
    "data": { 'a': '1' },
    "b": "1",
    "c": "2"
    }
    function copy(obj) {
    var newObj = {};
    for (var key in obj) {
    newObj[key] = obj[key];
    }
    return newObj;
    }
    var newObj = copy(obj);
    console.log(newObj)//{"data":{'a':'1'},"b":"1","c":"2"}
    newObj.data.a = 10;//二层对象进行的是浅拷贝
    newObj.b = 50;//一层对象进行生拷贝
    console.log(obj, newObj)//{"data":{'a':'10'},"b":"1","c":"2"},{"data":{'a':'10'},"b":"50","c":"2"}
    4、$.extend({},{})
    var obj = { data: { a: 1, b: 2, c: 3 } };
    var newObj = $.extend({}, obj);
    newObj.data.a = 10;
    console.log(obj, newObj)
    深拷贝
    1、Object.assign()
    前提是对象只有一层
    var obj = { a: 1, b: 2, c: 3 };
    var newObj = Object.assign({}, obj);
    newObj.a = 20;
    console.log(obj, newObj)
    2、$.extend()
    当第一个参数是true的时候是深拷贝 当不传递的时候是浅拷贝
    var obj = { data: { a: 1, b: 2, c: 3 } };
    var newObj = $.extend(true, {}, obj);
    newObj.data.a = 20;
    console.log(obj);
    console.log(newObj)
    3、JSON.stringify;但目标对象有要求(非 undefined,function)
    var obj = { data: { a: 1, b: 2, c: 3 } };
    var newObj = JSON.parse(JSON.stringify(obj));
    newObj.data.a = 20;
    console.log(obj);
    console.log(newObj)
    缺点是函数不能被赋值
    4.递归方法
    function deepClone(initalObj, finalObj) {
    var obj = finalObj || {};
    for (var i in initalObj) {
    if (typeof initalObj[i] === 'object') {
    obj[i] = (initalObj[i].constructor === Array) ? [] : {};
    arguments.callee(initalObj[i], obj[i]);
    } else {
    obj[i] = initalObj[i];
    }
    }
    return obj;
    }
    上述代码确实可以实现深拷贝。但是当遇到两个互相引用的对象,会出现死循环的情况。为了避免相互引用的对象导致死循环的情况,则应该在遍历的时候判断是否相互引用对象,如果是则退出循环。
    改进版代码如下:
    function deepClone(initalObj, finalObj) {
    var obj = finalObj || {};
    for (var i in initalObj) {
    var prop = initalObj[i];

    // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if (prop === obj) {
    continue;
    }

    if (typeof prop === 'object') {
    obj[i] = (prop.constructor === Array) ? [] : {};
    arguments.callee(prop, obj[i]);
    } else {
    obj[i] = prop;
    }
    }
    return obj;
    }
    使用的时候这样写:
            var Doctor = deepCopy(Chinese);
            现在,给父对象加一个属性,值为数组。然后,在子对象上修改这个属性:
             Chinese.birthPlaces = ['北京','上海','香港'];
              Doctor.birthPlaces.push('厦门');
            这时,父对象就不会受到影响了。
            alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
              alert(Chinese.birthPlaces); //北京, 上海, 香港
            目前,jQuery库使用的就是这种继承方法。

    5.使用Object.create()方法;直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。

    function deepClone(initalObj, finalObj) {
    var obj = finalObj || {};
    for (var i in initalObj) {
    var prop = initalObj[i];

    // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if (prop === obj) {
    continue;
    }

    if (typeof prop === 'object') {
    obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
    obj[i] = prop;
    }
    }
    return obj;
    }


  • 相关阅读:
    opencast的docker安装
    编译openwrt_MT7688_hiwooya
    linux中mysql自动同步
    网站服务器迁移
    vtigercrm安装
    ixcache的蜜汁突发故障
    20180628
    pip3 install -r requirements.txt安装超时解决方法
    pytest文档29-allure-pytest
    pytest框架
  • 原文地址:https://www.cnblogs.com/yunshangwuyou/p/9602183.html
Copyright © 2011-2022 走看看