You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript匿名函数是否会阻止垃圾回收器销毁变量?

问题:变量是否会被垃圾回收?

代码示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
</head>
<body>

    <button id="my-button">Do Something</button>
    <script type="text/javascript">
        let setButtonFunc;

        setButtonFunc = function() {
            let button = document.getElementById("my-button");
            let phrase = "Printing Something";

            button.onclick = function() {
                text = document.createTextNode(phrase);
                document.body.append(text);
            }
        }
        setButtonFunc();
        
        setButtonFunc = null;
    </script>

</body>
</html>

问题描述

我用let定义了setButtonFunc变量并赋值为一个函数,这个函数用来给按钮设置onclick事件,点击按钮时会往页面追加文本。

我的疑问是:把setButtonFunc设为null之后,phrase和button这两个变量会被垃圾回收器回收吗?

从逻辑上看,它们的引用好像都消失了,应该只有按钮的onclick函数留在内存里,其他变量因为没有外部引用会被回收。但实际点击按钮时,onclick函数还能正常执行,就像phrase从来没被释放过一样。

我搞不懂这点,比如在Python里做类似的操作,垃圾回收器会销毁变量并抛出异常。为什么JavaScript不会出现这种情况?是不是按钮的onclick匿名函数持有这些变量的引用?我是不是漏看了let的文档内容?


答案

  • phrase不会被垃圾回收,button会被回收
  • 核心原因是JavaScript的闭包机制:你赋值给button.onclick的匿名函数,会捕获它所在作用域(也就是setButtonFunc函数的作用域)里的phrase变量。哪怕外层函数setButtonFunc已经执行完毕,这个匿名函数依然持有对phrase的引用,所以垃圾回收器不会回收phrase。
  • 至于button变量:因为匿名函数里并没有用到它,所以这个变量不会被闭包捕获。当setButtonFunc执行完、setButtonFunc本身被设为null后,button就没有任何引用了,会被垃圾回收器回收。
  • 和Python的差异:Python也有闭包,但如果你的Python示例内层函数没有引用外层变量,或者外层变量未被持续持有,才会被回收。你觉得Python会抛出异常,大概率是因为你的Python示例中,内层函数尝试引用了已被销毁的变量,但在这个JS场景里,内层函数明确引用了phrase,闭包会把这个变量保留下来。
  • 关于let:你没漏看关键内容,let只是定义块级作用域的变量,闭包的规则不受let或var的影响(两者仅作用域范围不同),只要内层函数引用了外层作用域的变量,这个变量就会被闭包保留,不会被垃圾回收。

内容的提问来源于stack exchange,提问作者Carl HR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:15:42