乐趣区

关于javascript:JavaScript深浅拷贝区别

数据分为根本数据类型 (String, Number, Boolean, Null, Undefined,Symbol) 和对象数据类型。

  • 根本数据类型的特点:间接存储在栈 (stack) 中的数据
  • 援用数据类型的特点:存储的是该对象在栈中援用,实在的数据寄存在堆内存里

援用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找援用值时,会首先检索其在栈中的地址,获得地址后从堆中取得实体。

深拷贝和浅拷贝是只针对 Object 和 Array 这样的援用数据类型的 。最基本的区别在于是否真正获取一个 对象的复制实体,而不是援用。

假如 B 复制了 A,批改 A 的时候,看 B 是否发生变化:

如果 B 跟着 也变了,阐明是浅拷贝,拿人手短!(批改堆内存中的同一个值)

如果 B 没有扭转,阐明是深拷贝,自食其力!(批改堆内存中的不同的值)

浅拷贝(shallowCopy)只是减少了一个指针指向已存在的内存地址,

深拷贝(deepCopy)是减少了一个指针并且申请了一个新的内存,使这个减少的指针指向这个新的内存,

应用深拷贝的状况下,开释内存的时候不会因为呈现浅拷贝时开释同一个内存的谬误。

浅复制:仅仅是指向被复制的内存地址,如果原地址产生扭转,那么浅复制进去的对象也会相应的扭转。

深复制:在计算机中开拓一块 新的内存地址 用于寄存复制的对象。

浅拷贝实例:

 // 此递归办法不蕴含数组对象
    var obj = {a: 1, arr: [2, 3] };
    var shallowObj = shallowCopy(obj);

    function shallowCopy(src) {var newobj = {};
        for (var prop in src) {if (src.hasOwnProperty(prop)) {newobj[prop] = src[prop];
            }
        }
        return newobj;
    }

因为浅复制只会将 对象的各个属性 进行复制,并不会进行递归复制,而 JavaScript 存储对象是存地址的,所以浅复制会导致 Obj.arr 和 shallowObj.arr 指向同一块内存地址:

导致的后果就是:

shallowObj.arr[1] = 5;
console.log(obj.arr[1]); //5

深拷贝实例:

 var obj = {
        a: 1,
        arr: [1, 2],nation: '中国',
        birthplaces: ['北京', '上海', '广州']
    };
    var obj2 = {name: '杨'};
    obj2 = deepCopy(obj, obj2);
    console.log(obj2);
    // 深复制,要想达到深复制就须要用递归
    function deepCopy(o, c) {var c = c || {};
        for (var i in o) {if (typeof o[i] === 'object') {if (o[i].constructor === Array) {
                    // 这是数组
                    c[i] = [];} else {
                    // 这是对象
                    c[i] = {};}
                deepCopy(o[i], c[i]);
            } else {c[i] = o[i];
            }
        }
        return c;
    }

而深复制则不同,它不仅将原对象的各个属性一一复制进来,而且将原对象各个属性所 蕴含的对象 也顺次采纳深复制的办法递归复制到新对象上。这就不会存在 obj 和 shallowObj 的 arr 属性指向同一个对象的问题。

这样 obj1 和 obj2 别离领有不同的内存地址,两边的值扭转互不影响。

浅拷贝实现:

    var a = [1, 2, 3, 4, 5];
    var b = a;
    a[0] = 2
    console.log(a);
    console.log(b);

// 因为 b 浅拷贝 a, ab 指向同一个内存地址(堆内存中存的值)
// b 会随着 a 的变动而变动
//[2, 2, 3, 4, 5]
//[2, 2, 3, 4, 5]

深拷贝实现:

function deepClone(obj) {var newObj = obj instanceof Array ? [] : {};
        if (typeof obj !== 'object') {return obj;} else {for (var i in obj) {newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i];
            }
        }
        return newObj;
    }

    var a = [1, 2, 4, 6, "a", "12", [1, 2]];
    var b = deepClone(a);
    a[3] = 7;
    console.log(a);
    console.log(b);
    
    // b 对象并没有因为 a 对象的扭转而扭转,因为 b 深拷贝 a
      [1, 2, 4, 7, 'a', '12', [ 1, 2] ]
      [1, 2, 4, 6, 'a', '12', [ 1, 2] ]

退出移动版