JavaScript的深淺拷貝

存儲問題:
深拷貝和淺拷貝的主要區別:在內存中的存儲類型(堆和棧)不一樣
堆:動態分配的內存,大小不定也不會自動釋放
棧:自動分配的內存,由系統自動釋放
數據類型:javascript

基本數據類型:
javascript的基本數據類型5種:undefined null  number  string boolean
  • 存儲位置java

    棧。緣由:數據大小肯定,內存空間大小能夠分配,是直接按值存放的。

圖片描述

  • 值是否可變?數組

    基本數據類型值不可變,javascript中的原始值(undefined、null、布爾值、數字和字符串)與對象(包括數組和函數)有着根本區別。原始值是不可更改的:任何方法都沒法更改(或「突變」)一個原始值。對       數字和布爾值來講顯然如此 —— 改變數字的值自己就說不通,而對字符串來講就不那麼明顯了,由於字符串看起來像由字符組成的數組,咱們指望能夠經過指定索引來假改字符串中的字符。實際上,javascript 是禁止這樣作的。字符串中全部的方法看上去返回了一個修改後的字符串,實際上返回的是一個新的字符串值。
  • 基本類型的比較函數

    基本類型的比較是值的比較,只要兩個變量的值相等就認爲他們是相等的。
    比較最好用 === ,由於 == 會進行類型轉換,例如:var a = 1; var b= true;if(a==b) 則會返回true
引用數據類型(object):
  • 存儲位置

    堆。變量其實是存放在棧內存中的一個指針,這個指針指向堆內存中的地址,每一個空間大小不同,要根據狀況進行特定的分配。post

  • 值是否可變?

    引用類型值可變
    var a = [1,2,3];
    a[1] = 5;
    console.log(a[1]); // 5spa

  • 應用類型的比較

    引用類型的比較是引用的比較
    因此每次咱們對 js 中的引用類型進行操做的時候,都是操做其對象的引用(保存在棧內存中的指針),因此比較兩個引用類型,是看其的引用是否指向同一個對象。
    var a = [1,2,3];
    var b = [1,2,3];
    console.log(a === b); // false
    雖然變量 a 和變量 b 都是表示一個內容爲 1,2,3 的數組,可是其在內存中的位置不同,也就是說變量 a 和變量 b 指向的不是同一個對象,因此他們是不相等的。指針

傳值和傳址
  • 基本數據類型賦值code

    基本數據類型的賦值(=)是在內存中新開闢一段棧內存,而後再把再將值賦值到新的棧中。
        var a = 10;
        var b = a;
        a ++;
        console.log(a); // 11
        console.log(b); // 10
  • 引用數據類型賦值對象

    可是引用類型的賦值是傳址。只是改變指針的指向,例如,也就是說引用類型的賦值是對象保存在棧中的地址的賦值,這樣的話兩個變量就指向同一個對象,所以二者之間操做互相有影響。
      var a = {};  // a保存了一個空對象的實例 
      var b = a; // a和b都指向了這個空對象 
      a.name = 'jozo';
      console.log(a.name); // 'jozo' 
      console.log(b.name); // 'jozo' 
      b.age = 22; 
      console.log(b.age);  // 22 
      console.log(a.age);  // 22 
      console.log(a == b);// true
淺拷貝

那麼賦值和淺拷貝有什麼區別呢,咱們看下面這個例子:blog

var obj1 = {
    'name' : 'zhangsan',
    'age' :  '18',
    'language' : [1,[2,3],[4,5]],
};

var obj2 = obj1;


var obj3 = shallowCopy(obj1);
function shallowCopy(src) {
    var dst = {};
    for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
            dst[prop] = src[prop];
        }
    }
    return dst;
}

obj2.name = "lisi";
obj3.age = "20";

obj2.language[1] = ["二","三"];
obj3.language[2] = ["四","五"];

console.log(obj1);  
//obj1 = {
//    'name' : 'lisi',
//    'age' :  '18',
//    'language' : [1,["二","三"],["四","五"]],
//};

console.log(obj2);
//obj2 = {
//    'name' : 'lisi',
//    'age' :  '18',
//    'language' : [1,["二","三"],["四","五"]],
//};

console.log(obj3);
//obj3 = {
//    'name' : 'zhangsan',
//    'age' :  '20',
//    'language' : [1,["二","三"],["四","五"]],
//};

先定義個一個原始的對象 obj1,而後使用賦值獲得第二個對象 obj2,而後經過淺拷貝,將 obj1 裏面的屬性都賦值到 obj3 中。也就是說:

  • obj1:原始數據
  • obj2:賦值操做獲得
  • obj3:淺拷貝獲得

    而後咱們改變 obj2 的 name 屬性和 obj3 的 name 屬性,能夠看到,改變賦值獲得的對象 obj2 同時也會改變原始值 obj1,而改變淺拷貝獲得的的 obj3 則不會改變原始對象 obj1。這就能夠說明賦值獲得的對象 obj2 只是將指針改變,其引用的仍然是同一個對象,而淺拷貝獲得的的 obj3 則是從新建立了新對象。
    然而,咱們接下來來看一下改變引用類型會是什麼狀況呢,我又改變了賦值獲得的對象 obj2 和淺拷貝獲得的 obj3 中的 language 屬性的第二個值和第三個值(language 是一個數組,也就是引用類型)。結果見輸出,能夠看出來,不管是修改賦值獲得的對象 obj2 和淺拷貝獲得的 obj3 都會改變原始數據。
    這是由於淺拷貝只複製一層對象的屬性,並不包括對象裏面的爲引用類型的數據。因此就會出現改變淺拷貝獲得的 obj3 中的引用類型時,會使原始數據獲得改變。

  • 深拷貝:將 B 對象拷貝到 A 對象中,包括 B 裏面的子對象,
  • 淺拷貝:將 B 對象拷貝到 A 對象中,但不包括 B 裏面的子對象
深拷貝

深拷貝是對對象以及對象的全部子對象進行拷貝。

怎麼進行深拷貝?
思路就是遞歸調用剛剛的淺拷貝,把全部屬於對象的屬性類型都遍歷賦給另外一個對象便可
zepto深拷貝的例子還須要繼續瞭解深拷貝的實現方案。

相關文章
相關標籤/搜索