我是前端小白一枚,為了鞏固知識和增強記憶,開始整理相關的知識,方便以後複習和面試的時候看看。
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、利用遞迴的方式,遞迴所有層級的屬性;
function deepclone(obj) ;
// 判斷obj是否為object物件
列印出來的結果顯示,改變a,b沒有改變;
2、利用json.stringify()和json.parse();
function deepclone(obj)3、借用jq的extend方法$.extend( [deep ], target, object1 [, objectn ] )deep表示是否深拷貝,為true為深拷貝,為false,則為淺拷貝let a=[0,1,[2,3],4],
b=deepclone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
target
let a=[0,1,[2,3],4],講了這麼多,我們來說下用途,我們在開發中,如果有很多資料要處理,貿然的對資料進行增刪改的話,可能會存在汙染源資料問題,導致資料無法恢復;b=$.extend(true,,a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
深拷貝就幫助我們解決了這個隱患,我們就可以安心的去對資料進行相應的操作;
注:有些方法也可以實現拷貝,例如:slice()、assign()等方法,這兩個方式如果拷貝的層級只有一層為深拷貝,如果拷貝的層級是多層,那就是淺拷貝;
前端的深拷貝和淺拷貝 深拷貝與淺拷貝的區別
淺拷貝的方式 淺拷貝1 var obj var newobj obj newobj.name 李四 console.log obj console.log newobj 淺拷貝2 object.assgin 引數1 目標物件 引數2 任意多個物件 如果物件是多層的話 var obj var obj1...
js深拷貝與淺拷貝的區別及實現
其值在記憶體中佔據著固定大小的空間,並被儲存在棧記憶體中。當乙個變數向另乙個變數複製基本型別的值,會建立這個值的副本,並且我們不能給基本資料型別的值新增屬性。其為深拷貝。淺拷貝 只複製指向某個物件的指標,而不複製物件本身,新舊物件共享一塊記憶體 改變乙個物件,另乙個會隨之改變 深拷貝 複製並建立乙個...
前端深拷貝與淺拷貝
前端深拷貝與淺拷貝 1.淺拷貝 var obj1 var obj2 obj1 obj2.a 5 console.log obj1.a 5 console.log obj2.a 52.深拷貝 只能拷貝一層 var obj1 var obj2 object.assign obj1 obj2.c 1 5 ...