【问题标题】:javascript anonymous function garbage collectionjavascript匿名函数垃圾回收
【发布时间】:2011-09-11 22:12:24
【问题描述】:

如果我有这样的功能

function do(callback) {
  //do stuff
  callback();
}

然后我传入一个匿名函数:

do(function() { //do something else });

在页面的生命周期内是否会收集该匿名函数?如果没有,我怎样才能使它可用于 GC?

我必须这样做吗?

var h = function() { //do something };
do(h);
delete h;

我什至需要担心这个吗?我正在构建一个使用寿命长的网络应用程序,进行大量 ajax 调用将对象保留一段时间,并且实际上不需要刷新页面来导航。所以我想弄清楚我是否会陷入内存泄漏怪物。

【问题讨论】:

标签: javascript memory-leaks


【解决方案1】:

对匿名函数的唯一引用是函数参数,它会在函数完成时消失,因此之后您的回调将可用于垃圾回收。除非有其他东西引用它,这很容易在闭包中发生:

function doo(callback) {
    $.get(url, function() {
        // callback is visible here!
    });
    callback();
}
doo(function() { /* do something else */ });

callback(连同调用doo创建的整个作用域)必须留在内存中,因为内部函数可以通过闭包引用它;它只能在内部函数被垃圾回收时进行垃圾回收,并且由于该函数是jqXHR对象的属性,因此该对象必须在此之前进行垃圾回收,谁知道什么时候会发生......

更新你可以通过不在其他函数中定义你的函数来避免不必要的闭包:

var func = function() {
    // callback is not visible here
}
function doo(callback) {
    $.get(url, func);
    callback();
}
doo(function() { /* do something else */ });

【讨论】:

  • 如果我在 doo 函数 var var g = $; g.get... 中执行此操作会使回调可收集吗?或者我该怎么做才能让您的示例具有收藏价值?
  • @Jose: 用另一个名字指代$ 没有任何用处。我更新了我的答案以显示如何避免关闭。当然,如果您总是可以在对doo 的调用中重复使用相同的参数,而不是每次都创建一个匿名函数,那么这是解决问题的一种更简单的方法。
  • 我认为你的意思是“var func = function()...”而不是“var fun”...或者 $.get(url, func) 应该得到更新。
  • @Crashalot:已修复,谢谢。回想起来,虽然使用 deferred 会更优雅:function doo() { return $.get(url).then(function () {/*...*/}); }; doo().then(function() {/* do something else */});
  • @losnir,这取决于 JS 引擎。某些结构无法判断将使用哪些变量(例如 jsfiddle.net/x8xL8dwq ) - 现代浏览器以不同方式评估包含此类结构的代码,而旧版本则不会。
【解决方案2】:

注意循环引用,否则浏览器的 GC 会清除它们。闭包使创建循环引用变得非常容易,即使您浏览远离创建它的页面,它也可能被困在内存中。因此,长时间停留在屏幕上的 Web 应用程序尤其容易受到攻击。

在此处查看“内存泄漏”部分:https://developer.mozilla.org/en/A_re-introduction_to_JavaScript

我设计了很多静态页面 Web 应用程序。我发现即使您没有必须清理对象和事件处理程序(即您确定没有循环引用),它也不会受到伤害。它通常只添加几行额外的代码,并且在您编写代码时将内存使用和效率放在您头脑中的最前沿。这对 Web 开发人员来说是一种转变,因为我们在创建网站时通常不必考虑太多这类事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 2016-09-19
    • 2010-10-26
    • 1970-01-01
    相关资源
    最近更新 更多