var m = { a: 10,b:20 } var n = m;n . a = 15;//此時m.a的價值是多少?
M.a會輸出15,因為這是淺拷貝,n和m指向同壹個堆,對象拷貝只是對被拷貝對象的引用。
深層拷貝
深度拷貝和上面的淺拷貝不同,是完全拷貝壹個對象,而不是拷貝對象的引用。例如,和前面的例子壹樣,我們寫道:
var m = { a: 10,b: 20 }var n = {a:m.a,b:m . b };n . a = 15;
這次我們再輸出m.a,發現m.a的值還是10,沒有變化。雖然M對象和N對象的值都是壹樣的,但是在堆中是不壹樣的,這是深度復制。
深層拷貝和淺層拷貝
深層拷貝和淺層拷貝的示意圖大致如下:
淺層拷貝只拷貝指向壹個對象的指針,而不是對象本身,新舊對象仍然共享同壹個內存。但是,深層復制將創建另壹個相同的對象。新對象不與原對象共享內存,對新對象的修改不會改變原對象。
淺拷貝的實現
1可以通過簡單的賦值來實現。
當然,類似於上面的例子,我們也可以封裝壹個簡單的函數,如下:
函數simpleClone(initalObj) {
var obj = { };
for(initalObj中的變量I){
obj[I]= initalObj[I];
}
返回obj
}
var obj = {
答:“妳好”,
乙:{
答:“世界”,
乙:21
},
c:[“鮑勃”、“湯姆”、“珍妮”],
d:函數(){
alert(" hello world ");
}
}
var cloneObj = simple clone(obj);
console . log(cloneobj . b);
console . log(cloneobj . c);
console . log(cloneobj . d);
cloneobj . b . a = " changed ";
cloneObj.c = [1,2,3];
cloneobj . d = function(){ alert(" changed ");};
console . log(obj . b);
console . log(obj . c);
console . log(obj . d);2.Object.assign()的實現
Object.assign()方法可以將任意數量的源對象的可枚舉屬性復制到目標對象,然後返回目標對象。但是Object.assign()做的是淺層拷貝,拷貝的是對象屬性的引用,而不是對象本身。
var obj = { a: {a:“妳好”,b:21 } };var initalObj = Object.assign({},obj);initalobj . a . a = " changed ";console . log(obj . a . a);//“已更改”
註意:當對象只有壹層時,它是深層副本,如下所示:
var obj1 = { a: 10,b: 20,c:30 };var obj2 = Object.assign({},obj 1);obj 2 . b = 100;console . log(obj 1);// { a: 10,b: 20,c:30 } & lt;-_已更改為console . log(obj 2);/{A: 10,B: 100,C: 30}如何實現深度復制。
1,方法1或手動復印
像上面的例子,手動復制可以實現深度復制。
2.如果對象只有壹層,可以使用上面的:Object.assign()函數。
3.變成JSON再轉回來。
var obj 1 = { body:{ a:10 } };var obj 2 = JSON . parse(JSON . stringify(obj 1));obj 2 . body . a = 20;console . log(obj 1);//{ body:{ a:10 } } & lt;-_已更改為console . log(obj 2);//{ body:{ a:20 } } console . log(obj 1 = = = obj 2);//false console . log(obj 1 . body = = = obj 2 . body);// false使用JSON.stringify將對象轉換為字符串,然後使用JSON.parse將字符串轉換為新的對象。
您可以封裝以下函數
var cloneObj = function(obj){
var str,newobj = obj.constructor === Array?[] : {};
if(typeof obj!== 'object'){
返回;
} else if(窗口。JSON){
Str = JSON.stringify(obj),//序列化對象
new obj = JSON . parse(str);//恢復
}否則{
for(對象中的變量I){
new obj[I]= type of obj[I]= = = ' object '?
clone obj(obj[I]):obj[I];
}
}
返回newobj};4.遞歸復制
函數deepClone(initalObj,finalObj) {
var obj = final obj | | { };
for(initalObj中的變量I){
var prop = initalObj[I];//避免交叉引用對象導致無限循環,如initalObj.a = initalObj的情況。
if(prop === obj) {
繼續;
}
if (typeof prop === 'object') {
obj[I]=(prop . constructor = = = Array)?[] : {};
arguments.callee(prop,obj[I]);
}否則{
道具;
}
}
返回obj} var str = { }var obj = { a: {a:“妳好”,b:21 } };deepClone(obj,str);console . log(str . a);5.使用Object.create()方法。
直接使用var newObj = Object.create(oldObj)可以達到深度復制的效果。
函數deepClone(initalObj,finalObj) {
var obj = final obj | | { };
for(initalObj中的變量I){
var prop = initalObj[I];//避免交叉引用對象導致無限循環,如initalObj.a = initalObj的情況。
if(prop === obj) {
繼續;
}
if (typeof prop === 'object') {
obj[I]=(prop . constructor = = = Array)?[]:object . create(prop);
}否則{
道具;
}
}
返回obj}6、jquery
Jquery提供了壹個$。可用於深層復制的擴展。
var $ = require(' jquery ');var obj1 = {
答:1,
b: { f: { g: 1 } },
c: [1,2,3]};var obj2 = $。extend(true,{},obj 1);console . log(obj 1 . b . f = = = obj 2 . b . f);// false7、lodash
另壹個流行的函數庫Lodash也提供了_。深層復制的cloneDeep。
var _ = require(' lodash ');var obj1 = {
答:1,
b: { f: { g: 1 } },
c: [1,2,3]};var obj2 = _。cloneDeep(obj 1);console . log(obj 1 . b . f = = = obj 2 . b . f);// false這個性能還不錯,用起來也很簡單。
相信看完這些案例,妳已經掌握了方法。更多精彩請關註Gxl上其他相關文章!
相關閱讀:
HTML中最後壹行文字沒有完全顯示出來怎麽辦?
如何用css3制作圖標效果
如何轉換CSS的編碼