Javascript系列之浅复制与深复制

定义

浅复制

如果复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响。

深复制

深复制不是简单的复制引用,而是在堆中重新分配内存,并且把源对象实例的所有属性都进行新建复制,以保证深复制的对象的引用图不包含任何原有对象或对象图上的任何对象,复制后的对象与原来的对象是完全隔离的。

浅复制

数组浅复制

利用数组方法slice和concat返回新数组特性,进行复制。

var arr = [1,2,3];
var new_arr = arr.concat();
arr[0] = 'new';
console.log(new_arr);      //[1, 2, 3]

再来看一组情况:

var arr = [{name: 'haha'}, [1,2,3]];
var new_arr = arr.concat();
arr[0].name = "lily";
console.log(new_arr.name);      //"lily"

可以看出,如果数组元素是基本数据类型,就会复制一份,互不影响,而如果是对象或者数组,就会只复制对象和数组的引用。

扩展运算符

var obj = { name: "jack" };
var a = [1, 2];
var b = [3, obj];
a.push(...b);
a   // [1, 2, 3, {name: "jack"}]
a[3].name = "rose";
b   // [3, {name: "rose"}]

Object.assign

var obj = { name: "jack" };
var copyObj = Object.assign({}, obj);
obj.name = "rose";
copyObj   // {name: "rose"}

自定义浅复制

function shallowCopy(obj) {
    if (typeof obj !== 'object') return;
    var new_obj = obj instanceof Array ? [] : {};

    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            new_obj[key] = obj[key];
        }
    }
    return new_obj;
}
var source = {
    name: "source",
    child: {
        name:"child"
    },
    arr: [1,2,34],
    setName: function() { 
        this.name = "haha"; 
    }
};
var target = shallowCopy(source);
console.log(target);              //Object {name: "source", child:{ name:"child"}, arr: [1,2,34], setName: function }
source.child.name = "lily";
console.log(target.child.name);              //"lily"
source.name = "sam";
console.log(target.name);                   //"source"
source.arr[0] = 5;
console.log(target.arr);                   //"5,2,34"
source.setName = function() { console.log(this.name); };
console.log(target.setName );            //function(){ this.name = "haha";  }

由此可以看出,此方法确实可以复制object和array对象,但无法进行深复制;但是可以复制function。

深复制

对象深复制

利用JSON对象的parse和stringify方法。

var source = {
    name: "source",
    child: {
        name:"child"
    },
    arr: [1,2,34],
    setName: function() { 
        this.name = "haha"; 
    }
};
var target = JSON.parse(JSON.stringify(source));
console.log(target);              //Object {name: "source", child:{ name:"child"}, arr:[1,2,34] }
source.child.name = "lily";
console.log(target.name);              //"child"
source.arr[0] = 5;
console.log(target.arr);              //"1,2,34"

由此可以看出,虽然此方法确实可以复制object和array对象,并且进行了深复制,却无法复制function。

自定义深复制

function deepCopy(obj) {
    if (typeof obj !== 'object') return;
    var new_obj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            new_obj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
    }
    return new_obj;
}
var source = {
    name: "source",
    child: {
        name:"child"
    },
    arr: [1,2,34],
    setName: function() { 
        this.name = "haha"; 
    }
};
var target = deepCopy(source);
console.log(target);              //Object {name: "source", child:{ name:"child"}, arr: [1,2,34], setName: function }
source.child.name = "lily";
console.log(target.child.name);              //"child"
source.name = "sam";
console.log(target.name);                   //"source"
source.arr[0] = 5;
console.log(target.arr);                   //"1,2,34"
source.setName = function() { console.log(this.name); };
console.log(target.setName );            //function(){ this.name = "haha";  }

你可能感兴趣的:(复制,javascript)