javascript中的匿名函数

时间:2014-04-06 15:47:21

标签: javascript jquery firefox

我将匿名函数-A作为参数传递给另一个函数-B。即使在我调用B.destroy之后,函数A仍然存在并被执行,它甚至作为一个实时的匿名范围。我通过调试器发现了这种意外行为。以下是代码。

var  builder.record.verifyExplorer = new builder.VerifyExplorer(
    window.bridge.getRecordingWindow(),
    builder.getScript().seleniumVersion,
    function(step) {
      builder.getScript().addStep(step);
      builder.stepdisplay.update();
      // Don't immediately stop: this would cause the listener that prevents the click from
      // actually activating the selected element to be detached prematurely.
      setTimeout(function() { builder.record.stopVerifyExploring(); }, 1);
      window.bridge.focusRecorderWindow();
    }
  );

我通过将stopVerifyExploring定义为

来销毁上述功能
builder.record.stopVerifyExploring = function() {
  builder.record.verifyExploring = false;
  builder.record.verifyExplorer.destroy();
  builder.record.verifyExplorer = null;
  builder.record.continueRecording();
};

即使在调用了verifyExplorer.destroy之后,函数(步骤)仍然存在于匿名作用域中并被执行并执行所有不需要的操作。

通过替换

我有这种奇怪的行为
  jQuery(frame.document).bind(l, {}, ae.listeners[l], true);

  frame.document.addEventListener(l,ae.listeners[l],true);

在verifyExplorer中。我如何更改上面的代码导致意外行为?

所有这些都是我修复开源项目sebuilder中的错误的一部分。还有相关的post

1 个答案:

答案 0 :(得分:3)

行为完全没有意外,你没有取消计时器。

如果要取消定时器,请保存setTimeout的返回值,然后在/当您想要取消定时器时将该值传递到clearTimeout

发生了什么:

只要任何东西都引用它们,就会存在函数和对象。当你这样做时:

setTimeout(function() { builder.record.stopVerifyExploring(); }, 1);

...您在浏览器的计时器处理中保存了对该匿名函数的引用。该函数引用了创建它的上下文(以及所有包含上下文的内容)。因此,即使您执行verifyExplorer = null,也不会影响verifyExplorer对象用于引用所有的任何内容,也不会影响引用该对象的任何内容。它只是从特定变量中清除对该对象的引用。如果有其他未完成的引用(并且有),则该对象将保留在内存中。

在这种情况下,如果唯一未完成的引用是您已赋予setTimeout的功能,则清除超时(可能在destroy中)将释放浏览器的参考该函数释放该函数对其关闭的上下文的引用,并且这些函数可以进行垃圾收集。

更多(在我的博客上):Closures are not complicated