javascript匿名函数垃圾收集

javascript匿名函数垃圾收集,javascript,memory-leaks,Javascript,Memory Leaks,如果我有这样一个函数 function do(callback) { //do stuff callback(); } 然后我传入一个匿名函数: do(function() { //do something else }); 在页面的生命周期内,是否收集过匿名函数?如果没有,我如何将其提供给GC 我必须这样做吗 var h = function() { //do something }; do(h); delete h; 我真的要为此担心吗?我正在构建一个web应用程序,它有很长的

如果我有这样一个函数

function do(callback) {
  //do stuff
  callback();
}
然后我传入一个匿名函数:

do(function() { //do something else });
在页面的生命周期内,是否收集过匿名函数?如果没有,我如何将其提供给GC

我必须这样做吗

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

我真的要为此担心吗?我正在构建一个web应用程序,它有很长的使用寿命,可以进行很多ajax调用,可以将对象保留一段时间,并且不需要刷新页面就可以浏览。因此,我试图找出我是否会陷入内存泄漏怪兽。

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

请查看此处的“内存泄漏”部分:


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

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

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 */ });

对我来说,如果不删除我认为已删除的对象的事件侦听器,我往往会得到最多的内存泄漏。这里还有其他与JS相关的内存泄漏帖子,如果我在
doo
函数var
var g=$中这样做的话,您可能也想看看这里;g、 获取…
这会使回调变得可收集吗?或者我该怎么做才能让你的例子成为收藏品?@Jose:用另一个名字引用
$
没有任何用处。我更新了我的答案,以说明如何避免闭包。当然,如果您可以在调用
doo
时始终重用相同的参数,而不是每次都创建匿名函数,那么这是解决问题的更简单的方法。。。该选项或$.get(url,func)应得到更新。@Crashalot:已修复,谢谢。回过头来看,使用延迟函数可能会更优雅:
function doo(){return$.get(url).then(function(){/*…*/});};然后(函数(){/*执行其他操作*/})@losnir,这取决于JS引擎。有些结构使得不可能知道将使用哪些变量(例如)-现代浏览器对包含此类结构的代码的评估方式不同,而旧浏览器则不同。