在談javascript的淺復制和深復制之前,我們有必要在來討論下js的數據類型。我們都知道有Number,Boolean,String,Null,Undefined,Object五種類型。而Object又包含Function,Array和Object自身。前面的五種類型叫做基本類型,而Object是引用類型。可能有人就要問,為什么要分基本類型和引用類型呢?后面你就會明白的。
我們首先來看看淺復制和深復制的簡潔定義:
- 深復制:直接將數據復制給對應的變量
- 淺復制:將數據的地址復制給對應的變量
而數據類型和我們要討論的復制類型又有怎樣的聯系呢?我們試着摸索一下吧
實驗一:
1 var a = "dengkunming"; 2 var a1 = a; 3 alert(a1);//dengkunming 4 a="abc"; 5 alert(a1);//dengkunming;
這段代碼中我們把a賦值給a1,當a的值改變時,a1沒有發生變化。
實驗二:
1 var a = [0,1,2,3]; 2 var a1= a; 3 alert(a1);//[0,1,2,3] 4 a[1]="變"; 5 alert(a1);//[0,"變",2,3]
在這段代碼中我們同樣把a賦值給a1,當a的值改變的時候,a1卻發生了變化。
這是咋回事了,同樣的操作其結果怎么會有差異了?我們回頭看看,聰明的一休認為可能是這兩個a有些不同。那些不同了?前面的是字符串,后面的數組。好像就是我們前面提到的基本類型和數據類型吧。那我們把數據類型換一下看看會有什么結果。
實驗三:
1 var a = 3578; 2 var a1 = a; 3 alert(a1);//3578 4 a=8735; 5 alert(a1);//3578
實驗四:
1 1 var a = {w1:2,w2:3} 2 2 var a1= a; 3 3 alert(a1);//{w1:2,w2:3} 4 4 a1.w1="鄧"; 5 5 alert(a);//{w1:"鄧",w2:3}
在這兩組實驗中,我們把數據類型分別換成了Number型和Object類型。實驗三中可以發現a1不隨a值的變化而變化,實驗四中a會隨着a1的變化而變化(這里和實驗二略有不同,改變的是a1,當然你改變a的話,a1也會跟着變化)
似乎我們可以得出個一般性的結論了:
js中基本類型的賦值為深復制,而引用類型的賦值為淺復制。
現在有必要把深復制和淺復制的定義擴展一下了。
- 淺復制:就是把數據的地址賦值給對應變量,而沒有把具體的數據復制給變量,變量會隨數據值的變化而變化。
- 深復制:就是把數據賦值給對應的變量,從而產生一個與源數據不相干的新數據(數據地址已變化)。
實驗五:
1 var a = {w1:2,w2:3} 2 var a1= a; 3 alert(a1);//{w1:2,w2:3} 4 var a={x1:7,x2:8} 5 alert(a1);//{w1:2,w2:3}
按照我們上面的理論來講,這里是淺復制。a1應該隨着a的變化而變化呀,可在這里為什么會事與願違了?這就是引用類型惹的禍了。對象賦值其實都是引用傳值,傳遞的是一個地址。那么實驗五中的第四行其實就是把變量a指向了一個新的地址。而a1還是指向的原來那個地址,原來地址中的值沒變,所以a1就不會變。所以請記住:淺復制不會隨着存儲數據地址的變化而變化,只會隨着數據值的變化而變化。
那我們如何實現引用類型的深度復制呢?這就是老話題深度克隆了。就是需要自己寫一個非原生的clone函數嘍。
1 function clone(obj){ 2 var o=[]; 3 if(obj.constructor== Array) { 4 o=obj.slice(0); 5 }else{ 6 o={}; 7 for(var i in obj){ 8 o[i] = typeof obj[i] === "object" ? obj[i].clone() : obj[i];} 9 } 10 return o; 11 12 }
小可不才,文章中定會有所紕漏,望指出。也學一下大牛的語氣,此文原創,轉載請注明出處。如果你覺得文章還不錯,就怒頂並推薦一下下吧!!!!