談談 js 深淺拷貝 那點事(二)

找抽的小陀螺發表於2017-10-12

上篇 看到了從記憶體空間來看資料類在記憶體中存在情況 下面開始賣弄下js 深淺拷貝

  • 淺拷貝
    上篇瞭解到 基本型別拷貝 其實就是在棧中新開闢了一塊空間 原物件 跟拷貝出的物件是兩個互相獨立的東西
    這也就是說基本型別深淺都是一樣的 深淺拷貝相對引用型別

       var a = {
           key1: '123',
           key2: [4,5]
       }
       console.log(a) //key1:123  key2: 陣列
       function copy (a) {
          var obj = {}
          for (var i in a) {
              obj[i] = a[i]
          }
          return obj
       }
       var b = copy(a) //這裡棧記憶體中開闢了兩個空間 a b 這裡存放了物件的變數標識 跟 值(是引用型別就是指標)
    
       console.log(b.key1)  // 123 這個a  b 指標指向同一塊堆記憶體 key1 value值是123
       b.key3 = '333'
       console.log(b.key3) //333  
       console.log(a.key3) //undefined 
       這個是key3是一個基本資料型別在
       棧中b變數物件中值新增一個key3 並沒有通過指標 a  b  相互獨立  所以a是訪問不到的
       b.key2.push(8)
       console.log(b)// 這裡去操作b 在堆記憶體的key2屬性  因為a  b  都是同一個堆儲存  所以 a  b  都可以看到 key2陣列中新增了一個8複製程式碼

    資料結構

上面出現一個問題就是 a 拷貝到b 在b中的操作引用型別 就會導致a也會改變 因為指標指向同一塊堆記憶體
但是改變b中基本資料型別 並不會引起a 的改變 在a中是訪問不到的 因為a b 基本資料型別是放在棧記憶體中 是相互獨立互不影響的
所以深拷貝就出現了

  • 深拷貝
    如果物件屬性值型別是引用型別的話 只會傳址(指標) 就會影響原物件 那現在就要 把原物件中屬性為引用型別的 要迴圈的賦給 其他物件

      var a = {
           key1: '123',
           key2: [4,5]
       }
       function deepcopy (a, b){
           var b =b || {}
           for (var i in a) {
               if (typeof a[i] === 'object') {  //判斷屬性key2 是否物件
                  b[i] = (a[i].__proto__.constructor == Array) ? []: {}
                  deepcopy(a[i], b[i])  //遞迴
               } else {
                  b[i] = a[i]
               }
           }
           return b
       }
       var b = {}
       deepcopy(a,b)
       console.log(b)  //{key1: "123", key2: Array(2)}
       console.log(a)  //{key1: "123", key2: Array(2)}
       a.key3 = '333'
       console.log(a)  //{key1: "123", key2: Array(2), key3: '333'}
       console.log(b)  //{key1: "123", key2: Array(2)}
       基本資料型別a 中新增了個key3  這也看不出啥    基本型別在棧中 不會影響到b
       b.key2.push('44')
       console.log(a)  //{key1: "123", key2: Array(2), key3: '333'}
       console.log(b)  //{key1: "123", key2: Array(3)}  
       這樣在b 中新增了  對a 沒有了影響   基本資料型別是沒有影響的  引用型別感覺一個一個給拆出來弄成了棧存 不是通過指標指向堆存複製程式碼

    好了 有錯誤的希望給指出

    參考連結:
    關於JS堆疊與拷貝

相關文章