Javascript 中弱引用的查找表

2024-01-03

我有一个树结构,其中动态添加和删除元素。这些元素是从网络动态加载的。我想要实现的是拥有一个查找表,将元素的 id 映射到树中的实际元素。现在,使用简单的映射或对象时的问题是它持有对树元素的强引用,这会在一段时间后使内存膨胀。由于节点 >= 14.6.0 且 Chrome >= 84据说支持 WeakRef https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef我想我可以制作一个将 WeakRefs 保存到我的树元素的 Map,然后简单地deref()并查看元素是否仍然存在。我尝试对此进行测试,但似乎不起作用。我的最小测试如下所示:

const lookup = new Map();
let element = new Object({id:"someid", data: {}});

lookup.set(element.id, new WeakRef(element));
console.dir(lookup.get("someid").deref());
// as expected output is { id: 'someid', data: {} }

element = null;
console.log(element);
// as expected output is null

// simply calling global.gc() didn't work
// so i made this loop which allocates mem *and* calls global.gc() to
// force garbage collection
// problem: infinite loop because deref always returns the dereferenced
// value which should have gone since element was set to null

while (lookup.get("someid").deref()) {
  const a = new Array(1000);
  // enabled with --expose-gc in node
  global.gc();
}

console.dir(lookup.get("someid").deref());

正如上面评论中所写,问题是循环永远不会结束 因为 deref 调用总是返回一个值,尽管元素 var 被设置为空。

我在这里错过了什么吗?如果没有,这就是它应该如何工作的, 我怎样才能实现拥有弱引用映射的目标(WeakMap 不是 这里有一个选项,因为通过 id 查找元素的成本是 O(n)?。


我在这里错过了什么吗?

是的:您缺少注释中的注释文档 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef例如,您已链接到:

如果您的代码刚刚为目标对象创建了 WeakRef,或者从 WeakRef 的 deref 方法获取了目标对象,则该目标对象将不会被回收,直到当前 JavaScript 作业结束(包括在该作业运行的任何 Promise 反应作业)。脚本作业结束)。也就是说,您只能“看到”在事件循环的轮次之间回收对象。

而且当然:

尽可能避免
正确使用 Wea​​kRef 需要仔细考虑,并且最好尽可能避免。避免依赖规范未保证的任何特定行为也很重要。何时、如何以及是否发生垃圾收集取决于任何给定 JavaScript 引擎的实现。

也就是说,实现你的目标是完全有可能的;您的测试用例太简单(根据上面引用的注释),无法显示它。这是一个固定版本:

const lookup = new Map();

(function () {
  let element = { id: "someid", data: {} };
  lookup.set(element.id, new WeakRef(element));
  element = null;

  console.log(lookup.get("someid").deref());

  setTimeout(() => {
    global.gc();
    console.log(lookup.get("someid").deref());
  }, 0);
})();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascript 中弱引用的查找表 的相关文章

随机推荐

  • Delphi死锁解释/解决方案

    在服务器应用程序上 我们有以下内容 一个称为 JobManager 的单例类 另一个类是 Scheduler 它不断检查是否需要向 JobManager 添加任何类型的作业 当需要这样做时 调度程序会执行以下操作 TJobManager S
  • 让 Kubernetes 等待 Pod 终止,然后再从服务端点中删除

    根据Pod 的终止 https kubernetes io docs concepts workloads pods pod lifecycle pod termination 步骤 7 与 3 同时发生 有什么办法可以防止这种情况发生并且
  • R 中插入符中的并行处理

    插入符号文档中给出了允许并行处理以下代码的工作原理 library doMC registerDoMC cores 5 All subsequent models are then run in parallel 但在最新的 R 版本 3
  • jQuery 更改类名

    我想根据 td 标签的 id 更改 td 标签的类 td class change me 我希望能够在其他 dom 对象的单击事件中执行此操作 如何获取 td 的 id 并更改其类别 Using jQuery你可以set类 无论它是什么 w
  • 如何在 Spring Boot 中使用 @Lazy 延迟加载 RabbitMQ 队列?

    实际上 在我的 RabbitMQ 配置中 我为每个队列声明了 10 个消费者 因此 所有消费者线程都是在我的 Spring Boot 应用程序完全启动之前创建的 因此应用程序启动需要时间 我想在项目启动时延迟加载所有 Rabbitmq 队列
  • Python:使用泰勒级数逼近 ln(x)

    我正在尝试建立 ln 1 9 的近似值 精度在十位数字之内 即 641853861 我正在使用一个从 ln 1 x 1 x 构建的简单函数 到目前为止 这是我的代码 function for ln 1 x 1 x def taylor tw
  • 带鼠标滚轮的 D3 v4 平移

    如何使用 d3 js 版本 4 通过鼠标滚轮进行平移 我发现这个例子使用的是 v3 但它不适用于 v4 示例链接 http bl ocks org ahmohamed 82ac20ccc949470e3206
  • 如何禁用 Sun jvm 的内联优化?

    我需要做一些实验来展示内联对我的代码的影响 有人知道如何禁用 sun jvm 内联吗 我搜索了http www oracle com technetwork java javase tech vmoptions jsp 140102 htm
  • getRunningAppProcesses() 返回被销毁的进程

    我正在使用以下代码片段来检查我是否使用了应用程序finish ed 确实不再运行 ActivityManager am ActivityManager this getSystemService ACTIVITY SERVICE List
  • 即使库已链接,对符号的未定义引用

    当链接我正在处理的项目时 链接器给出以下错误 usr bin ld Includes and Libs lib libsfml21rca a SoundFile o undefined reference to symbol sf read
  • javafx 和可序列化

    在旧的 AWT 库中 Point类和Color类是可序列化的 JavaFX 中都没有 我想保存一个数组列表Drawable到一个文件 这是界面 import javafx scene canvas GraphicsContext publi
  • mouseover() mouseout() jQuery add/removeClass 问题

    我正在尝试使用 mouseover mouseout addClass 和 removeClass 的组合来创建一个简单的鼠标悬停效果 基本上 当用户将鼠标悬停在某个元素上时 我想应用不同的边框 1px 灰色虚线 初始状态为 1px 纯白色
  • Groovy 可以动态添加或重写 POJO 上的方法吗?

    如果我有 java class MyClass public String getName return hector 和这个类的一个实例 Groovy 可以重写实例上的 getName 方法吗 当然你可以使用动态元类 http groov
  • 创建一个包含开始日期和结束日期之间的日期的列表

    使用 SQL Server 2016 我有一个具有不同开始日期和结束日期的表 Start End 2018 01 01 00 00 2018 01 01 23 59 2018 01 12 05 33 2018 01 13 13 31 201
  • 如何在玩笑中模拟/监视 useState 挂钩?

    我试图监视 useState React hook 但我总是测试失败 这是我的 React 组件 const Counter gt const counter setCounter useState 0 const handleClick
  • 如何从本地maven存储库中删除通过install:install-file添加的jar文件?

    mvn install install file Dfile phonegap 1 1 0 jar DgroupId phonegap DartifactId phonegap Dversion 1 1 0 Dpackaging jar 我
  • System.ArgumentException 路径中存在非法字符

    我在用Path Combine 并且其中一个字符串包含 Unicode 字符 我明白了 System ArgumentException exception illegal characters in path 根据MSDN http ms
  • 转换 UTF8 文本以在 URL 中使用

    我正在开发一个国际网站 它使用 UTF8 显示非英语字符 我还使用包含项目名称的友好 URL 显然我不能在 URL 中使用非英文字符 这种转换有某种常见的做法吗 我不确定应该用哪些英文字符替换它们 有些字符非常明显 例如 到 e 但其他字符
  • Gradle 7.2:如何应用自定义 Gradle SETTINGS 插件?

    我正在将 buildSrc 约定插件迁移到独立插件中 有很多为 Project 对象创建 Gradle 插件的示例 但真正缺乏 Settings 和 Gradle 我想集中我们在 gradle settings kts 文件中使用的存储库列
  • Javascript 中弱引用的查找表

    我有一个树结构 其中动态添加和删除元素 这些元素是从网络动态加载的 我想要实现的是拥有一个查找表 将元素的 id 映射到树中的实际元素 现在 使用简单的映射或对象时的问题是它持有对树元素的强引用 这会在一段时间后使内存膨胀 由于节点 gt