日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

你还在用乞丐版的深拷贝么

發布時間:2023/12/16 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你还在用乞丐版的深拷贝么 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

你還在用乞丐版的深拷貝么

乞丐版:JSON.parse(JSON.stringify());


這種寫法非常簡單,而且可以應對大部分的應用場景,但是它還是有很大缺陷的,比如拷貝其他引用類型、拷貝函數、循環引用等情況。

?

?

基礎版本

如果是淺拷貝的話,下面的很容易:

?

function clone(target){let cloneTarget = {};for (const key in target) {cloneTarget[key] = target[key];}return cloneTarget; }

?

創建一個新的對象,遍歷需要克隆的對象,將需要克隆對象的屬性依次添加到新對象上,返回。

?


如果是深拷貝的話,考慮到我們要拷貝的對象是不知道有多少層深度的,我們可以用遞歸來解決問題,稍微改寫上面的代碼:

  • 如果是原始類型,無需繼續拷貝,直接返回
  • 如果是引用類型,創建一個新的對象,遍歷需要克隆的對象,將需要克隆對象的屬性執行深拷貝后依次添加到新對象上。

很容易理解,如果有更深層次的對象可以繼續遞歸直到屬性為原始類型,這樣我們就完成了一個最簡單的深拷貝:

?

function clone (target) {if (typeof target === 'object') {let cloneTarget = {};for (const key in target) {cloneTarget[key] = clone(target[key])}return cloneTarget;} else {return target;} }

?

這是一個最基礎版本的深拷貝,這段代碼可以讓你向面試官展示你可以用遞歸解決問題,但是顯然,他還有非常多的缺陷,比如,還沒有考慮數組。

?

考慮數組

?

在上面的版本中,我們的初始化結果只考慮了普通的object,下面我們只需要把初始化代碼稍微一變,就可以兼容數組了:

?

function clone(target) {if (typeof target === 'object') {let cloneTarget = Array.isArray(target) ? [] : {};for (const key in target) {cloneTarget[key] = clone(target[key]);}return cloneTarget;} else {return target;} };

?

循環引用

?

const target = {field1: 1,field2: undefined,field3: {child: 'child'},field4: [2, 4, 8] }; target.target = target;

?

解決循環引用問題,我們可以額外開辟一個存儲空間,來存儲當前對象和拷貝對象的對應關系,當需要拷貝當前對象時,先去存儲空間中找,有沒有拷貝過這個對象,如果有的話直接返回,如果沒有的話繼續拷貝,這樣就巧妙化解的循環引用的問題。

?

這個存儲空間,需要可以存儲key-value形式的數據,且key可以是一個引用類型,我們可以選擇Map這種數據結構:

  • 檢查map中有無克隆過的對象
  • 有 - 直接返回
  • 沒有 - 將當前對象作為key,克隆對象作為value進行存儲
  • 繼續克隆
function clone(target, map = new Map()) {if (typeof target === 'object') {let cloneTarget = Array.isArray(target) ? [] : {};if (map.get(target)) {return map.get(target);}map.set(target, cloneTarget);for (const key in target) {cloneTarget[key] = clone(target[key], map);}return cloneTarget;} else {return target;} };

?

接下來,我們可以使用,WeakMap提代Map來使代碼達到畫龍點睛的作用。

?


為什么要這樣做呢?,先來看看WeakMap的作用:

WeakMap 對象是一組鍵/值對的集合,其中的鍵是弱引用的。其鍵必須是對象,而值可以是任意的。

什么是弱引用呢?

在計算機程序設計中,弱引用與強引用相對,是指不能確保其引用的對象不會被垃圾回收器回收的引用。 一個對象若只被弱引用所引用,則被認為是不可訪問(或弱可訪問)的,并因此可能在任何時刻被回收。

我們默認創建一個對象:const obj = {},就默認創建了一個強引用的對象,我們只有手動將obj = null,它才會被垃圾回收機制進行回收,如果是弱引用對象,垃圾回收機制會自動幫我們回收。

舉個例子:

如果我們使用Map的話,那么對象間是存在強引用關系的:

let obj = { name : 'ConardLi'} const target = new Map(); target.set(obj,'code秘密花園'); obj = null;

雖然我們手動將obj,進行釋放,然是target依然對obj存在強引用關系,所以這部分內存依然無法被釋放。

再來看WeakMap:

let obj = { name : 'ConardLi'} const target = new WeakMap(); target.set(obj,'code秘密花園'); obj = null;

如果是WeakMap的話,target和obj存在的就是弱引用關系,當下一次垃圾回收機制執行時,這塊內存就會被釋放掉。

設想一下,如果我們要拷貝的對象非常龐大時,使用Map會對內存造成非常大的額外消耗,而且我們需要手動清除Map的屬性才能釋放這塊內存,而WeakMap會幫我們巧妙化解這個問題。

?

https://juejin.cn/post/6844903929705136141#heading-2

?

總結

以上是生活随笔為你收集整理的你还在用乞丐版的深拷贝么的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。