天天看點

clone是深拷貝還是淺拷貝_手寫系列——JS深拷貝和淺拷貝

不要問我心裡有沒有你,我餘光中都是你。——餘光中
clone是深拷貝還是淺拷貝_手寫系列——JS深拷貝和淺拷貝

概念補漏

1. 堆棧的概念

在計算機中,堆棧是兩種資料結構。
  • 棧(stack):先進後出;動态配置設定的空間 一般由程式員配置設定釋放, 若程式員不釋放,程式結束時可能由OS回收,配置設定方式倒是類似于連結清單。
  • 堆(heap):隊列優先,先進先出;由作業系統自動配置設定釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于資料結構中的棧。

2.基本,引用資料類型

  • 7種基本資料類型:   Undefined、Null、Boolean、Number、String、Symbol(es6新增)、BigInt(es10新增), 基本資料類型都存儲在棧中,每種資料類型的記憶體空間大小是确定的,是以便于及時回收,更加容易管理記憶體空間。
  • 1種引用資料類型: Object 。這其中包含了 object、array、function、date等等,這樣的資料存儲于堆中。但是其引用類型的資料存儲在棧記憶體中,如果需要通路可以通過先擷取到對象的指針位址,然後通過指針位址通路堆中的對應資料。

JavaScript不支援任何建立自定義類型的機制,而所有值最終都将是以上 8 種資料類型之一(排除之後新增)。

  • 為了便于了解我做了一個示範。
    clone是深拷貝還是淺拷貝_手寫系列——JS深拷貝和淺拷貝
  • 堆棧圖
    clone是深拷貝還是淺拷貝_手寫系列——JS深拷貝和淺拷貝

3.淺拷貝和深拷貝

淺拷貝:簡單的說淺拷貝就是隻進行一層的拷貝,對對象的屬性第一層進行拷貝,不管之後的層級。

深拷貝:對對象的屬性無限層級的拷貝。

代碼示範

這是我覺得現在比較好的深淺拷貝方式,随着語言的發展,之後類型的增多,會有一定的增删。
  • 淺拷貝
    // shallowCopyconst isObject = (o) => typeof o === 'object' && o !== null;const shallowCopy = (obj) => {  if (!isObject(obj)) return obj;  const res = Array.isArray(obj) ? [] : {};  for (const key in obj) {    if (obj.hasOwnProperty(key)) {      const element = obj[key];      res[key] = element;    }  }  return res;};
               
  • 深拷貝
    // deepCopyconst isObject = (o) => typeof o === 'object' && o !== null;const deepCopy = (obj, weakmap = new WeakMap()) => {  if (!isObject(obj)) return obj;  // 解決循環引用, 防止無限周遊  if (weakmap.get(obj)) return weakmap.get(obj);  // 建立新對象存入weakmap  const target = Array.isArray(obj) ? [] : {};  weakmap.set(obj, target);  // symbol拷貝  const symArr = Object.getOwnPropertySymbols(obj);  symArr.forEach((key) => {    if (isObject(obj[key])) {      target[key] = deepCopy(obj[key], weakmap);    } else target[key] = obj[key];  });  // 對象的key  for (const key in obj) {    if (obj.hasOwnProperty(key)) {      if (isObject(obj[key])) {        target[key] = deepCopy(obj[key], weakmap);      } else target[key] = obj[key];    }  }  return target;};
               

參考文檔

WeakMap MDN文檔