如果你想真正自己理解和運用深度轉殖的話,首先必須要了解的就是js中的原始值和引用值,以及它們的儲存位置及方式。這裡簡單的說一下,原始值是儲存在棧裡的,而且儲存的是變數的實際值。引用值儲存在堆裡,且儲存的是乙個指標,該指標指向記憶體中的某個位置,該位置儲存變數的實際值。
var a =2;
var a_copy = a ;
a_copy =3;
console.
log(a)
;var arr =[1
,2,3
,4];
var arr_copy = arr ;
arr_copy.
push(5
);console.
log(arr)
;var obj =
;var obj_copy = obj ;
obj_copy.name =
'過客'
;console.
log(obj.name)
;
最終輸出結果如下:
可以看出當複製引用值(陣列、物件)時,修改複製後的變數,原來的變數也跟著變了,原因就是當引用值複製時複製的是指標,所以修改它們的變數時指標沒有改變,而是指標指向的值變了,所以指向同一指標的原變數也就變了,不過在有一種情況下,修改複製後的變數,被複製的變數不會跟著改變,那就是複製後,給複製變數重新定義值得時候,原來的變數不會受影響,因為此時已經給複製後的變數重新分配指標了。
var arr =[1
,2,3
,4];
var arr_copy = arr ;
arr_copy =[1
,2,3
,4,5
];console.
log(arr)
;console.
log(arr_copy)
;var obj =
;var obj_copy = obj ;
obj_copy =
;console.
log(obj.name)
;console.
log(obj_copy.name)
;
最終輸出結果如下:
對於乙個引用型別,如果直接將它賦值給另乙個變數,由於這兩個引用指向同乙個位址,這時改變其中任何乙個引用,另乙個都會受到影響。當我們想複製乙個物件並且切斷與這個物件的聯絡,就要使用深拷貝。
有點麻煩但是通用的方法prototype判斷變數的型別,由於函式具有不可遍歷性,所以儘管函式也是引用值,我們也可以按照淺度的方法複製即可。
var userinfo =
}function
gettype
(obj)
else
if(object.prototype.tostring.
call
(obj)
=='[object array]'
)else
}function
deepcopy
(obj)
else:[
];for(
var key in obj)}}
return newobj;
}var newinfo =
deepcopy
(userinfo)
;newinfo.name =
'過客。。。。'
;console.
log(newinfo)
;console.
log(userinfo)
;
最終結果輸出如下:
這裡用到.hasownproperty是為了避免在拷貝有繼承時拷貝到繼承自物件中的值(也就是a繼承b,使用.hasownproperty就是為了只拷貝a中的變數,過濾繼承自b中的變數。)
深度拷貝和淺度拷貝
文字說明 比如乙個陣列 array 淺度拷貝是當陣列a變數成陣列b的時候,b改變裡面的陣列數值的時候,a也隨著改變,深度拷貝是噹噹陣列a變數成陣列b的時候,b改變裡面的陣列數值的時候,a裡面的陣列陣列不隨著改變,那麼為什麼淺度拷貝會改變a的陣列值而深度拷貝則不會呢?因為淺度拷貝指向的是同乙個記憶體,...
js深度拷貝和淺度拷貝的深入理解
首先我們來說說什麼是拷貝 就是複製的同時加上了傳值。然後問題就來了什麼是有深度的什麼是淺度的,在想要了解我們這個問題之前我們先來了解一下下面的乙個知識點 基本型別傳遞,引用型別傳遞 首先我們來看下基本型別傳遞 就是基本資料型別之間的資料傳遞,什麼是基本資料型別呢?string,number,bool...
js深拷貝與淺拷貝
1 基礎知識 基本型別與引用型別 js中可以把變數分成兩部分,基本型別和引用型別。基本型別包括 undefined null boolean number和string 引用型別值可能由多個值構成的物件。在對基礎型別資料進行拷貝時,實際相當於建立新的相同資料 hello 賦值給b var a hel...