1. 程式人生 > >值型別和引用型別,深層複製和淺層複製(深拷貝淺拷貝)最詳細了

值型別和引用型別,深層複製和淺層複製(深拷貝淺拷貝)最詳細了

要知道深層複製淺層複製的區別,首先要了解值型別和引用型別。

變數分值型別和引用型別,深層複製和淺層複製都是針對引用型別變數的操作。

值型別: 比如數值,字串,布林,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~