js 深拷貝和淺拷貝

Thales發表於2022-03-30

定義

深拷貝:複製物件與原物件互不影響
淺拷貝:複製物件與原物件首層互不影響

常見的深拷貝

  1. JSON.parse(JSON.stringify())
  2. 手動封裝deepCopy

常見的淺拷貝

  1. Object.assign()
  2. es6擴充套件運算子
  3. shallowCopy

原理

首先我們要了解無論深拷貝還是淺拷貝都是對引用資料型別而言,基礎資料型別是不存在深淺拷貝的概念的,為什麼呢?讓我們先來了解連個儲存空間--棧和堆

棧:自動分配,儲存空間小,一般用來儲存確定空間大小的資料,自動釋放記憶體
堆:儲存空間大,儲存不確定空間大小的資料,需要手動釋放記憶體

上面我們簡單的介紹了棧堆特點,js的基礎資料型別一般都是確定了儲存空間的大小,也就是是說每一個基礎資料型別都是獨立存在棧中互不影響所以不存在深淺拷貝,而引用資料型別則不是他們儲存在堆中,通過呼叫棧中的引用地址來訪問堆引用資料,多個引用地址指向同一塊堆中記憶體,當我們修改資料是其實是通過引用地址修改堆中的記憶體資料,所以牽一髮而動全身,有時這種現象是我不不想看到的,所以出現了深淺拷貝

所以原理很簡單,將我們需要切斷聯絡的資料重新開闢一款記憶體空間這樣我們就完成了深淺拷貝

深拷貝:所有屬性都會開闢一塊新的記憶體空間,來切斷與原物件的聯絡
淺拷貝:只在首層屬性開闢新的記憶體空間,如果原物件多層巢狀其餘巢狀層依然複製引用地址

例子:

// 深拷貝 正反序列 JSON.parse(JSON.stringify())
var obj = {
  name:'zs',
  info:{
    age: 18,
    sex: '男'
  }
}

var obj1 = JSON.parse(JSON.stringify(obj))
obj1.name = 'ls'
obj1.info.age = 22
console.log(obj.name,obj.info.age,obj1.name,obj1.info.age) // zs 18 ls 22
// 淺拷貝 擴充套件運算子
var obj = {
  name:'zs',
  info:{
    age: 18,
    sex: '男'
  }
}

var obj1 = {...obj}
obj1.name = 'ls'
obj1.info.age = 22
console.log(obj.name,obj.info.age,obj1.name,obj1.info.age)  // zs 22 ls 22
// 淺拷貝 Object.assign
var obj = {
  name:'zs',
  info:{
    age: 18,
    sex: '男'
  }
}

var obj1 = Object.assign({},obj)
obj1.name = 'ls'
obj1.info.age = 22
console.log(obj.name,obj.info.age,obj1.name,obj1.info.age) // zs 22 ls 22

注意:Object.assign 第一個引數不是空物件或空陣列它僅僅是複製記憶體地址

相關文章