本文主要介紹深拷貝和淺拷貝的概念及區別。
咱們先從堆和棧提及。
1、堆和棧
堆和棧都是內存中劃分出來用來存儲的區域。segmentfault
棧(stack)爲自動分配的內存空間,它由系統自動釋放;而堆(heap)則是動態分配的內存,大小不定也不會自動釋放。
2、數據類型
數據分爲基本數據類型(String, Number, Boolean, Null, Undefined,Symbol)和引用數據類型(Object,Array...)。數組
基本數據類型的特色:直接存儲在棧(stack)中的數據
引用數據類型的特色:存儲的是該對象在棧中引用,真實的數據存放在堆內存裏函數
引用數據類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址後從堆中得到實體。spa
3、賦值=淺拷貝??3d
先來講賦值
對於基本數據類型來講,賦值無需多說。基本類型的賦值的兩個變量是兩個獨立相互不影響的變量。
可是引用類型的賦值是傳址。只是改變指針的指向,例如,也就是說引用類型的賦值是對象保存在棧中的地址的賦值,這樣的話兩個變量就指向同一個對象,所以二者之間操做互相有影響。指針
var a = { name:'weiwei' }; var b = a; // 新建一個b對象,地址指向a指向的堆 a.name='ww'; console.log(a.name); // 'ww' console.log(b.name); // 'ww' b.age = 22; console.log(b.age);// 22 console.log(a.age);// 22
附上圖片說明一張(迷之畫風)
code
該案例說明了引用類型賦值時傳的是地址指向,當一個改變時另外一個也會被改變。對象
再來講說淺拷貝
淺拷貝只複製一層對象的屬性,並不包括對象裏面的爲引用類型的數據。blog
let a = { id:1, age: {name:1} } function shallowCopy(src) { var dst = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop]; } } return dst; } let b=shallowCopy(a); b.id=2;//id爲第一層屬性,改變淺拷貝後的,原來不會改變 console.log(a.id); //1 b.age.name=2;//name爲第二層屬性,改變淺拷貝後的,原來會改變 console.log(a.age.name); //2
實現淺拷貝的方法Object.assign()
遞歸
let a = { age: 1 } let b = Object.assign({}, a); a.age = 2; console.log(b.age); // 1
另外咱們還能夠經過展開運算符...
來實現淺拷貝
let a = { age: 1 } let b = { ...a } a.age = 2 console.log(b.age) // 1
淺拷貝只解決了第一層的問題,若是接下去的值中還有對象的話,那麼就又回到最開始的話題了,二者享有相同的地址。要解決這個問題,咱們就得使用深拷貝了。
4、深拷貝
1.JSON.parse(JSON.stringify())
原理: 用JSON.stringify將對象轉成JSON字符串,再用JSON.parse()把字符串解析成對象,一去一來,新的對象產生了,並且對象會開闢新的棧,實現深拷貝。
這種方法雖然能夠實現數組或對象深拷貝,但不能處理函數
2.手寫遞歸方法
遞歸方法實現深度克隆原理:遍歷對象、數組直到裏邊都是基本數據類型,而後再去複製,就是深度拷貝。
3.函數庫lodash
該函數庫也有提供_.cloneDeep用來作 Deep Copy
後續將不斷更新完善,期待您的批評指正!