深拷貝與淺拷貝 (遞歸、Object.assign({},obj)、JSON操作)

一個引用對象一般來說由兩個部分組成:一個具名的Handle,也就是我們所說的聲明(如變量)和一個內部(不具名)的對象,也就是具名Handle的內部對象。它在Manged Heap(託管堆)中分配,一般由新增引用對象的New方法是進行創建。

深拷貝是指源對象與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響( 指的是拷貝一個對象時,不僅僅把對象的引用進行復制,還把該對象引用的值也一起拷貝。這樣進行深拷貝後的拷貝對象就和源對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。)

淺拷貝:拷貝出來的目標對象的指針和源對象的指針指向的內存空間是同一塊空間,淺拷貝只是一種簡單的拷貝,讓幾個對象公用一個內存,然而當內存銷燬的時候,指向這個內存空間的所有指針需要重新定義,不然會造成野指針錯誤。
深拷貝的方法

1.JSON.parser(JSON.stringfy(obj));
【注意】如果obj裏面有undefined或者function時,不會被拷貝過去
el:

var obj={
a:1,
b:2,
c:undefined,
fn:function(){}
}
var b=JSON.parse(JSON.stringify(obj));
console.log(b);
console.log(obj);
console.log(b===obj);

a: 1b: 2
a: 1b: 2c: undefined fn: ? ()
false

2.遞歸

function deepCopy(obj){
var newobj=Array.isArray(obj)?[]:{};
for(let item in obj){
if(typeof(obj[item])=="object" && obj[item]){
newobj[item]=deepCopy(obj[item]);
} else{
newobj[item]=obj[item];
}
}
return newobj
}
console.log(deepCopy(obj),obj);
console.log(deepCopy(obj)===obj); //false

3.利用數組的Array.prototype.forEach進copy

let deepClone = function (obj) {
    let copy = Object.create(Object.getPrototypeOf(obj));
    let propNames = Object.getOwnPropertyNames(obj);
    propNames.forEach(function (items) {
        let item = Object.getOwnPropertyDescriptor(obj, items);
        Object.defineProperty(copy, items, item);

    });
    return copy;
};

let testObj = {
    name: "weiqiujuan",
    sex: "girl",
    age: 22,
    favorite: "play",
    family: {brother: "wei", mother: "haha", father: "heihei"}
}
let testRes2 = deepClone(testObj);
console.log(testRes2);

Object.assign() 只是一級屬性複製,比淺拷貝多深拷貝了一層而已。除第一層外不在深拷貝

var obj={
a:1,
b:{
c:1,
d:2
},
e:function(){

}
}
var obj1=Object.assign({},obj);
obj1.m=10;
obj1.b.c=444;
obj1.n={kk:000}
console.log(obj1,obj,"iiiiiii");
console.log(obj1===obj)//false
1.obj1
{a: 1, b: {…}, e: ?, m: 10, n: {…}}
    1.
a: 1
    2.
b: {c: 444, d: 2}
    3.
e: ? ()
    4.
m: 10
    5.
n: {kk: 0}
    6.
__proto__: Object
2.obj
{a: 1, b: {…}, e: ?}
    1.
a: 1
    2.
b: {c: 444, d: 2}
    3.
e: ? ()
4.

proto: Object
//第一層爲深拷貝,改變obj1裏面第一層的數據時obj不會發生改變,但是改變obj1的第二層的時候,obj會發生改變,所以第二層是淺拷貝
淺拷貝的方法:

var obj={
a:1,
b:{
a:1,
b:2
},
c:function(){

}
}
var b=obj;
b.a=10;
console.log(b,obj);
b.b.a=10;
console.log(b,obj)
console.log(b===obj)

//當改變b裏面的屬性值的時候obj裏面相應的屬性值也會發生改變

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章