值型別和引用型別,深層複製和淺層複製(深拷貝淺拷貝)最詳細了
要知道深層複製淺層複製的區別,首先要了解值型別和引用型別。
變數分值型別和引用型別,深層複製和淺層複製都是針對引用型別變數的操作。
值型別: 比如數值,字串,布林,undifined
引用型別 : 比如陣列,物件,函式
來張圖(手抖,有點醜):
var num = 77;
var id = 1234;
var cat = {name : '喵喵',age : 3 };
結合上面圖,記憶體分兩塊區域,棧和堆。
值型別的資料儲存在棧中;
引用型別的儲存需要棧和堆共同完成,在棧中存放地址,該地址指向對應的堆記憶體中的資料。
看看區別
值型別:
var name = '周小七';
var other= name ;
name = '周小八'
console.log(other) ; //'周小七'
console.log(name == other) ;//false
引用型別:
var seven1 = {};
var seven2 = seven1;
seven1.name = '周小七';
console.log(seven2.name); //'周小七'
console.log(seven1 == seven2);//true
為什麼? 因為他們都是指向同一個物件的,再來個醜圖,哈哈:
基礎講完,開始看拷貝:
物件的例項是儲存在堆記憶體中然後通過一個引用值去操作物件,由此拷貝的時候就存在兩種情況了:拷貝引用和拷貝例項,這也是淺拷貝和深拷貝的區別。
淺拷貝
以上面的為例,var seven2 = seven1,這就是淺層複製,拷貝之後,seven1===seven2,這是淺拷貝的一種情況,直接拷貝源物件的引用,另外一種情況有點複雜,拷貝源物件的例項,但如果其屬性值為複雜的資料型別,只拷貝其內層元素的引用,啥意思?上程式碼:
var a = [{m:1}, {n:2},3]; var b = a.slice(); console.log(b);//[{m:1}, {n:2},3] console.log(a === b);// false a[0].m = 4; console.log(b[0].m)//4,說明拷貝的是元素的引用 a[2] = 5; console.log(b[2])//3,說明拷貝的例項,(拷貝的a上面的3)
我拷貝你的時候,你裡面屬性值是值型別的,我直接拷走,你值型別再變化,我不受影響;你裡面的屬性值如果是複雜一些的引用型別,太重了,我拷不走,那我就只拷貝指向它的地址,當你這邊值變化時,我那邊也跟著變。一句話概括就是,看人下菜碟。哈哈哈,勢利眼。。。。
深拷貝
深拷貝是克隆了一個一模一樣的物件,目標是使 seven1 != seven2,深拷貝會開闢新的記憶體區域,地址指向不同的地方。深拷貝後的物件與原來的物件是完全隔離,互不影響
深拷貝怎麼實現?
1. 來個最簡單粗暴的(我個人常用),哈哈:
seven2 = JSON.parse(JSON.stringify(seven1));
大部分的時候可以用,侷限:函式不能複製;原型鏈搞沒了...
2. jQuery.extend() : 用於將一個or多個物件內容合併到目標物件:
$.extend( [deep ], target, object1 [, objectN ] )
deep預設false---淺拷貝(第二種淺拷貝,拷貝例項,內層屬性值引用型別時,只拷貝內層元素的引用)
deep設定true---深拷貝,上程式碼:
var a = [{m:1}, {n:2},3]; var b =[]; $.extend(true,b,a); console.log(a === b);// false a[0].m = 4; console.log(b[0].m)//1 a[2] = 5; console.log(b[2])//3
這樣無論a再怎麼變化,都不會影響到b了。
呼~~完事,寫的不能再詳細了趕腳~,還畫圖簡直累死寶寶惹,o(╥﹏╥)o~