JS引用類型數據的淺拷貝與深拷貝

淺拷貝


以前文章提到,在定義一個對象或數組時,變量存放的每每只是一個地址。當咱們對堆內存中的對象複製時,若是屬性是對象或數組時,這時候咱們拷貝的只是一個棧內存指針。所以b對象在訪問該屬性時,會根據指針尋找到a對象指向的堆內存對象,二者的屬性值會指向同一內存空間數組

var a = {
    key1:"11111"
}
function Copy(p) {
    var c = {};
    for (var i in p) { 
      c[i] = p[i];
    }
    return c;
}
a.key2 = ['小輝','小輝'];
var b = Copy(a);
b.key3 = '33333';
alert(b.key1);     //1111111
alert(b.key3);    //33333
alert(a.key3);    //undefined
//對象中key1屬性是字符串,key2屬性是數組。a拷貝到b,12屬性均順利拷貝。給b對象新增一個字符串類型的屬性key3時,b能正常修改,而a中無定義。說明子對象的key3(基本類型)並無關聯到父對象中,因此undefined。

b.key2.push("大輝");
alert(b.key2);    //小輝,小輝,大輝
alert(a.key2);    //小輝,小輝,大輝

可是,若修改的屬性變爲對象或數組時,那麼對象之間就會發生關聯。從以上彈出結果可知,對b對象進行修改,a、b的key2屬性值(數組)均發生了改變。其在內存的狀態,能夠用下圖來表示。spa

clipboard.png


深拷貝

不但願對象之間產生關聯,那麼這時候能夠用到深拷貝。既然屬性值類型是數組和或對象時只會傳址,那麼咱們就用遞歸來解決這個問題,把要複製的對象中全部屬於對象的屬性類型都遍歷賦給新對象便可。指針

function Copy(p, c) {
    var c = c || {};
    for (var i in p) {
      if (typeof p[i] === 'object') {
         c[i] = (p[i].constructor === Array) ? [] : {};
         Copy(p[i], c[i]);
      } else {
         c[i] = p[i];
      }
    }
    return c;
    }    
a.key2 = ['小輝','小輝'];
var b={};
b = Copy(a,b);        
b.key2.push("大輝");
alert(b.key2);    //小輝,小輝,大輝
alert(a.key2);    //小輝,小輝

過程以下圖code

clipboard.png

相關文章
相關標籤/搜索