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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

WeakMap 本身释放,而 keyObject 没有释放的情况下,value 会释放吗?

發布時間:2025/3/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WeakMap 本身释放,而 keyObject 没有释放的情况下,value 会释放吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

博客園markdown不太好看,可以轉到git閱讀https://sologgfun.github.io/look/

const keyObject = ['keyObject']; new WeakMap().set(keyObject, ['value']);

問題:現在 ['value'] 會被釋放嗎?

聽說WeakMap是o(1)復雜度的,而且不會存在內存泄漏問題,那么就只有一種實現機制,就是value直接通過一個隱形鍵掛在keyObject上。

但如果是這樣,而WeakMap本身又沒有引用它之前添加過那些內容,那么是不是如果keyObject不釋放,即便WeakMap實例釋放了,通過該WeakMap實例添加在keyObject上的value是不是也都不會釋放,從而形成另一種內存泄漏?

jsperf.com只能測試性能,不知道內存泄漏該如何測試?


答案:會正確被釋放

測試過程:

[1]Chrome DevTools 控制臺上有一個小眾的 API 叫

queryObjects()

,它可以從原型樹上反查所有直接或間接的繼承了某個對象的其它對象,比如

queryObjects(Array.prototype)

可以拿到所有的數組對象,

queryObjects(Object.prototype)

則基本上可以拿到頁面里的所有對象了(除了繼承自Object.create(null)的對象之外)。而且關鍵是這個 API 會在內存里搜索對象前先進行一次垃圾回收

【測試1】

const key = new WeakMap(); const map = new WeakMap(); map.set(key, new WeakMap()); undefined;

在chrome控制臺運行

查到了 3 個對象,符合預期

【測試2】

const key = new WeakMap(); new WeakMap().set(key, new WeakMap()); undefined;

在chrome控制臺運行

只有一個WeakMap沒有被回收


那么WeakMap是怎么做到的呢?

核心在于WeakMap上的kv對是弱引用的

V8 的實現,是在 GC 上開洞的
https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/objects/hash-table.h#L336

https://github.com/v8/v8/blob/4b9b23521e6fd42373ebbcb20ebe03bf445494f9/src/heap/scavenger.cc#L465WeakMap

里用的就是這個 EphemeronHashTable,EphemeronHashTable 存儲著的鍵和值都是弱引用

let wm = new WeakMap([[k1, v1], [k2, v2]]) // vm = {k1:v1, k2:v2}wm.size // no such propertywm.keys(); // no such functionwm.forEach(...) // unable to be iterated

WeakMap有2個特點

  • 屬性不可枚舉
  • key必須是Object類型
  • 看一下WeakMap的polyfill

    var WeakMap = function() {this.name = '__wm__' + uuid() };WeakMap.prototype = {set: function(key, value) {Object.defineProperty(key, this.name, {value: [key, value],});return this;},get: function(key) {var entry = key[this.name];return entry && (entry[0] === key ? entry[1] : undefined);},... };
  • weakmap.set(key, val)事實上是直接通過Object.defineProperty給這個key加了一個新屬性
  • —— WeakMap的key必須是Object類型的原因

  • 相比Map,WeakMap持有的只是每個鍵值對的“弱引用”,不會額外開內存保存鍵值引用。這意味著在沒有其他引用存在時,垃圾回收器能正確處理key指向的內存塊。
  • —— WeakMap的key不可枚舉的原因


    延伸閱讀

    1.Object.defineProperty(obj, "prop", propDesc)和obj.prop = value的區別?

    [譯]JavaScript中的屬性:定義和賦值的區別

    2.什么是弱引用?

    垃圾回收機制不考慮對該對象的引用。

    也就是說,如果其他對象都不再引用該對象,那么垃圾回收機制會自動回收該對象所占用的內存,不考慮該對象是否還在該弱引用的結構中。

    WeakMap不能遍歷,是因為成員都是弱引用,隨時可能消失,遍歷機制無法保證成員的存在,很可能剛剛遍歷結束,成員就取不到了。


    參考資料

  • https://www.zhihu.com/question/344771857
  • https://www.jianshu.com/p/8c4ffa77b346
  • http://es6.ruanyifeng.com/#docs/set-map#WeakSet
  • 轉載于:https://www.cnblogs.com/cndotabestdota/p/11552309.html

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的WeakMap 本身释放,而 keyObject 没有释放的情况下,value 会释放吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

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