實現淺拷貝與深拷貝

2022-01-10 12:05:22 字數 3271 閱讀 4357

js包含基本資料型別與引用資料型別兩種不同的資料型別的值,深拷貝與淺拷貝的概念只存在於引用資料型別。對於引用型別,淺拷貝是拷貝了指向這個物件堆記憶體的指標,是拷貝了對原物件引用,深拷貝是拷貝了該物件的所有屬性到乙個新的物件,若是原物件的某屬性依然引用了其他物件,那麼需要將原物件引用的其他物件一併進行深拷貝,並不斷遞迴進行。對於基本資料型別是不存在深拷貝與淺拷貝的概念的,如果將乙個基本資料型別變數的值賦值到另乙個變數,那麼新變數的值是對於原變數值的複製而不是引用,如果必須要按照深淺拷貝的概念理解的話,對於基本資料型別的複製可以理解為按值深拷貝。

原生方法實現淺拷貝,可以使用object.assign({}, obj)等方式,主要是使用了spread操作符將物件表示式展開構造字面量物件的方式實現淺拷貝,對於object.assign({}, obj)是執行了一次將可列舉屬性複製到目標物件並返回目標物件的操作。關於object.assign是淺拷貝還是對於第一層是深拷貝之後是淺拷貝的說法,主要取決於如何理解淺拷貝與深拷貝的概念,假如同本文一樣認為只有引用型別才有淺拷貝與深拷貝的概念的話,那麼object.assign就是淺拷貝;假如認為對於基本資料型別也有淺拷貝與深拷貝的概念的話,那麼如上文所述對於基本資料型別的拷貝可以理解為按值深拷貝,那麼關於object.assign第一層是深拷貝,第二層及以後是淺拷貝的說法也是沒有問題的。

原生方法實現深拷貝,主要是使用json.parse()json.stringify(),首先將物件序列化為json字串,再將json字串反序列化為物件,使用這種方式效率比較高,但是會有一些問題,對於迴圈引用的物件無法實現深拷貝,對於被拷貝的物件,如果物件中有屬性為date物件,此種方式深拷貝會將時間物件轉化為字串;如果物件中有屬性為regexp物件、error物件,此種方式深拷貝會得到乙個空物件;如果物件中有屬性為function物件、undefinedsymbol值,此種方式深拷貝會忽略這些值;如果物件中有屬性為naninfinity-infinity,此種方式深拷貝會將結果轉為null

function shallowcopy(target, origin)

function deepcopy(target, origin)

// 淺拷貝測試 將origin中屬性淺拷貝到target

var target = {}

var origin =

}shallowcopy(target, origin);

console.log(target, origin); // } }

origin.a.aa = 11;

console.log(target, origin); // } }

// 深拷貝測試 將origin中屬性深拷貝到target

var target = {}

var origin =

}deepcopy(target, origin);

console.log(target, origin); // } }

origin.a.aa = 11;

console.log(target, origin); // } }

對於淺拷貝,只需要處理被拷貝物件的所有的可列舉屬性進行賦值即可。

對於深拷貝,需要將基本資料型別進行賦值,然後對物件屬性進行遞迴處理。

function shallowcopy(target, origin)

function deepcopy(target, origin), origin[item]);

}else if(origin[item] instanceof array)else if(origin[item] instanceof date)else if(origin[item] instanceof regexp)else

}else

}return target;

}// 淺拷貝測試 將origin中屬性淺拷貝到target

var target = {}

var origin =

}shallowcopy(target, origin);

console.log(target, origin); // } }

origin.a.aa = 11;

console.log(target, origin); // } }

// 深拷貝測試 將origin中屬性深拷貝到target

var target = {}

var origin = ,

cc: [1, ],

dd: new date().gettime(),

ee: /./g

} }deepcopy(target, origin);

console.log(target, origin);

/* a: bb:

cc: [1, ] cc: [1, ]

dd: 1390318311560 dd: 1390318311560

ee: /./g ee: /./g

} }

*/origin.a.aa = 11;

origin.a.bb.bbb = 11;

origin.a.cc[0] = 11;

origin.a.cc[1].ccc = 11;

origin.a.dd = new date().gettime();

origin.a.ee = /./gi;

console.log(target, origin);

/* a: bb:

cc: [1, ] cc: [11, ]

dd: 1390318311560 dd: 1390318792391

ee: /./g ee: /./gi

} }

*/

「淺拷貝」與「深拷貝」

c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...

淺拷貝與深拷貝

淺拷貝 1 2 myclass a,b a b 為了封裝性和解耦,同型別的兩個物件之間進行賦值操作時,所有成員變數被複製,包括私有成員 指標變數。類的成員函式在傳遞或返回物件時都會進行物件複製產生臨時物件,比如函式呼叫時實參變為形參,以及函式返回物件。考慮到效能和使用者要求不同,編譯器不複製物件內部...

「淺拷貝」與「深拷貝」

c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...