js?淺拷貝和深拷貝

堆和棧

棧(stack)為自動(dòng)分配內(nèi)存空間,它由系統(tǒng)自動(dòng)釋放。堆(heap)則是動(dòng)態(tài)分配內(nèi)存,大小不定也不會(huì)自動(dòng)釋放

數(shù)據(jù)類型
  • 基本數(shù)據(jù)類型:Boolean, String, Number, undefined, null, Symbol
    保存在棧中
  • 引用類型:Object
    數(shù)據(jù)保存在堆中, 指針保存在棧中
淺拷貝

對象只會(huì)被克隆最外部的一層,對于子對象,依然通過引用指向同一塊堆內(nèi)存

  • Object.assign方式 Object.assign(target, source1, source2)
  • for...in...
function shallowClone (obj) {
  const cloneObj = {}
  for (let i in obj) {
    cloneObj[i] = obj[i]
  }
  return cloneObj
}
深拷貝
  • JSON.parse(JSON.stringify(obj))


    JSON.parse(JSON.stringify(obj)拷貝

    我們可以看到,obj和arr正??截悾莇ate變成了字符串,reg變成了空對象,fun直接不見了。所以該方法只能拷貝一些簡單的對象,不適合復(fù)雜對象的拷貝。

  • for...in...加遞歸
const isObj = (obj) => (typeof obj === 'object' || typeof obj === 'function') && obj !== null
function deepClone(obj) {
  const tempObj = Array.isArray(obj) ? [] : {}
  for (let i in obj) {
    tempObj[i] = isObj(obj[i]) ? deepClone(obj[i]) : obj[i]
  }
  return tempObj
}

拷貝的結(jié)果是:


for..in加遞歸拷貝的結(jié)果

我們看到此時(shí)date、fun、reg都變成了空對象

  • 環(huán)
    環(huán)就是對象循環(huán)引用,導(dǎo)致自己成為一個(gè)閉環(huán)
    如:
    閉環(huán)

    對閉環(huán)進(jìn)行拷貝時(shí)報(bào)錯(cuò):
    爆棧

    可以使用WeakMap結(jié)構(gòu)存儲(chǔ)被保存的對象,每一次被拷貝時(shí)就先向WeakMap查詢。
function deepClone(obj, map = new WeakMap()) {
  if (map.has(obj)) {
    return has.get(obj)
  }
  const tempObj = Array.isArray(obj) ? [] : {}
  map.set(obj, tempObj)
  for (let i in obj) {
    tempObj[i] = isObj(obj[i]) ? deepClone(obj[i]) : obj[i]
  }
  return tempObj
}
  • 結(jié)合以上,解決Date、RegExp、Function的深拷貝如下
function deepClone (obj, map = new WeakMap()) {
  let cloneObj
  let Constructor = obj.constructor
  switch (Constructor) {
    case Date:
      cloneObj = new Constructor(obj.getTime())
      break
    case RegExp:
      cloneObj = new Constructor(obj)
      break
    case Function:
      cloneObj = function () {
        const temp = function temporary() { return this.apply(obj, arguments) }
        for( let key in obj ) {
          if (obj.hasOwnProperty(key)) {
            temp[key] = obj[key]
          }
        }
        return temp
      }
      break
    default:
      if (map.has(obj)) {
        return map.get(obj)
      }
      cloneObj = new Constructor()
      map.set(obj, cloneObj)
      break;
  }
  for (const key in obj) {
    cloneObj[key] = isObj[obj[key]] ? deepClone(obj[key]) : obj[key]
  }
  return cloneObj
}
拷貝結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 文章開始前。我們必須要知道的是 深淺拷貝是針對于引用數(shù)據(jù)而言的,對于基本數(shù)據(jù)類型并沒有深淺拷貝的區(qū)分。希望此文章 ...
    小小小小的人頭閱讀 408評論 0 3
  • 淺拷貝:Array.prototype.concat()拷貝數(shù)組,Object.assign() 拷貝對象1.兩個(gè)...
    吖蛋黃閱讀 254評論 0 0
  • 寫在前面 各類技術(shù)論壇關(guān)于深拷貝的博客有很多,有些寫的也比我好,那為什么我還要堅(jiān)持寫這篇博客呢,之前看到的一篇博客...
    心_c2a2閱讀 21,500評論 3 18
  • 第一章 錯(cuò)誤處理: 錯(cuò)誤: 程序運(yùn)行過程中,導(dǎo)致程序無法正常執(zhí)行的現(xiàn)象(即bug) 現(xiàn)象: 程序一旦出錯(cuò),默認(rèn)會(huì)報(bào)...
    fastwe閱讀 1,254評論 0 1
  • 清早5點(diǎn)多,就被雞鳴聲吵醒,好不容易熬到天亮,趕緊起床, 出門在村子里走了一下。黃色的菜花開得正艷,公雞仍在不知疲...
    寧波紫滿閱讀 1,654評論 0 0

友情鏈接更多精彩內(nèi)容