javascript - 递归 setTimeout 调用是否会导致闭包链内存泄漏?

标签 javascript recursion memory-leaks settimeout

我有以下情况:

let func = () => {
  //...
  let id = setTimeout(() => {
    console.trace();
    clearTimeout(id);
    func();
  }, 2000);
}

func();

例如,如果我们在 Chrome 控制台中运行以下代码,我们会得到以下堆栈跟踪

console.trace
(anonymous) @ VM89644:4
setTimeout (async)
func @ VM89644:3
(anonymous) @ VM89644:6
setTimeout (async)
func @ VM89644:3
(anonymous) @ VM89644:6
setTimeout (async)
func @ VM89644:3
(anonymous) @ VM89644:6
setTimeout (async)
func @ VM89644:3
(anonymous) @ VM89644:6
setTimeout (async)
func @ VM89644:3
(anonymous) @ VM89644:6
setTimeout (async)
func @ VM89644:3
(anonymous) @ VM89644:6
...
...
...

每次迭代都会不断增加。最终它达到了一个最大值(我认为在 35 次迭代之后),链似乎停止增长,但我很好奇是否只是 Chrome 不显示它。到底发生了什么?

最佳答案

Does a recursive setTimeout call cause a closure chain memory leak?

没有。每次触发计时器后,浏览器中的计时器子系统都会释放其与计时器函数的链接,而计时器函数又会释放其与创建它的环境的链接,从而允许它们都被回收。

which keeps increasing on every iteration. Eventually it reaches a maximum point (i think after 35 iterations) where the chain seems to stop growing but I'm curious if it's simply Chrome just not displaying it. What exactly is happening?

这是标准的内存管理,根据 JavaScript 引擎的内存管理启发式清理事物,这并不总是主动清理事物。我怀疑如果您反复点击开发工具的“收集垃圾”按钮(在“内存”选项卡上),您会发现它回到了接近基线的水平。

可能阻止返回到接近基线的一件事是 V8 的漂亮 async stack traces 。它们被宣传为“零成本”,但当然,这不可能完全正确,因为它们必须跟踪异步堆栈信息(即使只是作为字符串)。

关于javascript - 递归 setTimeout 调用是否会导致闭包链内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56955686/

相关文章:

ios - ffmpeg中的内存泄漏

javascript - 如何让其他广告在 Google 网站上发挥作用?例如 Adbrite 代码未链接图片

javascript - 是否可以通过代码触发 dojo 特定的事件?

javascript - Highcharts柱状系列点对象点击功能

recursion - 汉诺塔 : Recursive Algorithm

C++ 递归深度优先搜索迷宫算法和现在去哪里?

PHP 递归数组循环和格式化

javascript - 如何改进(消除太多标记?)JavaScript 中的慢正则表达式?

c - C什么时候释放struct的内存

java - 启动 Activity 内存泄漏