我是前端小白一枚,為了鞏固知識和增強記憶,開始整理相關的知識,方便以后復習和面試的時候看看,
OK,讓我們進入正題~
先說說淺拷貝和深拷貝的理解吧,個人是這樣理解的:
兩個物件A、B, A有資料B為空,B復制了A,我們修改A,如果B中的資料跟著變化了,那就是淺拷貝,如果沒有變化,那就是深拷貝,說明B另開辟了一塊記憶體(下文會講解),
舉個栗子:
AB兩個物件,我只改變了A中的元素,為什么B中的元素也跟著變化了?(上面是一個淺拷貝的栗子)

要深入理解淺拷貝和深拷貝的原理,那就要涉及到一些基本資料型別和參考資料型別的知識了;
基本資料型別:number,string,boolean,null,undefined,symbol等;
參考資料型別:object({}物件,陣列[]),function函式等;
因為拷貝是對資料進行操作,所以我們得了解一下這兩類的資料存盤方式;
基本資料型別一般存盤在堆疊中;參考資料型別一般存放在堆中; 話不多說上圖!
a.基本型別--屬性名,屬性值存盤在堆疊記憶體中,例如var a=1;

當你b=a復制時,堆疊記憶體會新開辟一個記憶體,例如這樣:


當我們修改a = 2時,b中的資料沒有改變;
我們可以得出,基本資料型別中,復制一個物件,會在堆疊中開辟一塊新記憶體,改變其中一個物件另一個物件不會受影響;但是這不是深拷貝,深拷貝只針對較為復雜的object資料型別;
b.參考資料型別--屬性名存在堆疊記憶體中,屬性值存在于堆記憶體中,但是堆疊記憶體會提供一個參考的地址指向堆記憶體中的值,我們以上面淺拷貝的例子畫個圖:

當b=a進行拷貝時,其實復制的是a的參考地址,而并非堆里面的值,

而當我們a[0]=1時進行陣列修改時,由于a與b指向的是同一個地址,所以自然b也受了影響,這就是所謂的淺拷貝了,

那,要是在堆記憶體中也開辟一個新的記憶體專門為b存放值,就像基本型別那樣,豈不就達到深拷貝的效果了

OK,了解了什么是淺拷貝和深拷貝后,那怎么實作深拷貝呢?
深拷貝的實作:
1、利用遞回的方式,遞回所有層級的屬性;
列印出來的結果顯示,改變a,b沒有改變;
2、利用json.stringify()和json.parse();
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
3、借用JQ的extend方法
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷貝,為true為深拷貝,為false,則為淺拷貝
target Object型別 目標物件,其他物件的成員屬性將被附加到該物件上,
object1 objectN可選, Object型別 第一個以及第N個被合并的物件,
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
講了這么多,我們來說下用途,我們在開發中,如果有很多資料要處理,貿然的對資料進行增刪改的話,可能會存在污染源資料問題,導致資料無法恢復;
深拷貝就幫助我們解決了這個隱患,我們就可以安心的去對資料進行相應的操作;
注:有些方法也可以實作拷貝,例如:slice()、assign()等方法,這兩個方式如果拷貝的層級只有一層為深拷貝,如果拷貝的層級是多層,那就是淺拷貝;
這是我的第一篇博客,以后會慢慢寫一些東西發表一下,一來是可以用于面試復習,二來又可以對這些知識復習,可以加強記憶;
如果有寫的不好的地方或者有問題的地方,歡迎大家一起討論;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/96619.html
標籤:JavaScript
上一篇:Composition API
下一篇:堆疊
