javascript - 为什么游戏代码继续运行而不是被垃圾收集?

标签 javascript garbage-collection

我有这段代码,它在窗口 onload 事件触发后创建一个匿名游戏实例。

由于整个函数都是匿名的,并且对游戏对象的引用没有保存在任何地方,我真的很惊讶这个游戏能运行!

为什么myGame在window.onload之后没有被处理掉? 我知道垃圾收集不会立即发生,但我也从未见过 myGame 实例在随机时刻突然消失。 Game 类中的哪种代码能够防止实例被垃圾回收?是对 DOM 的引用吗?

Game.js

(function(window){
    window.onload = function() { 
        // create a game instance but don't save the reference anywhere
        var myGame = new Game();
    };

    function Game() {

        var myCar;
        this.name = "Main App";

        this.init = function(){
            this.logMessage("creating a game instance");
        }

        this.logMessage = function(msg) {
            document.getElementById("message").innerHTML += msg + "</br>";
        }

        this.init();
    }
})(window);  

最佳答案

Why does Game code keep running instead of being garbage collected?

事实并非如此。它设置消息,然后立即符合 GC 条件。消息仍然显示的事实并不意味着您的游戏实例仍在内存中或其代码仍在运行。

该代码中没有任何内容阻止 Game instance 被 GC。除非有原因(内存压力等),否则 GC 可能不会发生,但是使用如此简单的代码,现代引擎甚至可能不需要应用 GC(例如,V8 可能会分配您的实例 on堆栈,然后弹出堆栈;如果您的代码在 onload 返回后保留引用,它会在退出时将其复制到堆中。

Is it the references to the DOM?

不,由于方向(您的游戏实例 DOM 元素)。它必须是另一种方式。 (此外,您不会保留任何正在检索的引用文献。)

What kind of code inside the Game class would be able to keep the instance from being garbage collected?

导致直接或间接引用游戏实例的任何内容。例如,只是改变

var myGame = new Game();

window.myGame = new Game();

会这样做,因为现在 window 有一个直接引用游戏实例的属性。

或者在 init 中添加这样的代码:

var self = this;
document.getElementById("message").addEventListener("click", function() {
    this.innerHTML = self.name;
}, false);

因为现在,该 DOM 元素具有对该事件处理函数的引用,该函数又具有对其创建时的上下文的引用,该上下文具有对 Game 实例的引用。


请注意,在您的代码中,Game(函数),因为分配给 window.onload 的闭包会关闭Game 创建的上下文。我们可以看到,如果我们深入挖掘 Chrome 的堆快照:

enter image description here

...但是 Game instance 创建并(简要地)分配给 myGame 不会保留。


FWIW,在 Chrome 中,如果我运行你的代码并做一个堆快照并搜索 Game 的实例,我没有看到任何东西:

enter image description here

如果我修改您的代码以保留实例:

window.myGame = new Game();

然后我做:

enter image description here

关于javascript - 为什么游戏代码继续运行而不是被垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34416616/

相关文章:

javascript - 使用原型(prototype)函数作为事件处理程序会导致内存泄漏吗?

haskell - 频繁的 GC 会阻止并行运行 Spark

c# - GC 的固定实例 - 无法从我的托管代码中追踪

javascript - 使用 md-select Angular js 打印选项中的所有内容

javascript - 使用 Raphael's-library 绘制左对齐文本

javascript - JavaScript 中的键值对

javascript - 无法将多个视频插入播放列表 - YouTube API v3

Javascript 垃圾收集通知

.net - 在使用 .NET : always, 的响应式扩展时,永远不会或有时会保留对 `IDisposable` 的引用?

Javascript函数执行范围