【问题标题】:Javascript: named closure and memory managementJavascript:命名闭包和内存管理
【发布时间】:2018-02-17 01:03:16
【问题描述】:

我正在尝试更多地了解 JS 中的内存管理,但我对闭包有一些疑问。

案例1:

// Suppose that object var is capable to emit events 
var object = new EventEmitter();

object.addEventListener('custom-event', function callback(event) {
    object.removeEventListener('custom-event', callback);
    object = null;

    //Do some heavy computation like opening a specific view or somehthing similar
    var heavy_window = new HeavyWindow();
    heavy_window.open();
});

案例2:

// Suppose that object var is capable to emit events 
var object = new EventEmitter();

object.addEventListener('custom-event', callback = function(event) {
    object.removeEventListener('custom-event', callback);
    object = null;

    //Do some heavy computation like opening a specific view or somehthing similar
});

我的问题是:

  • 案例一:

    • 认为object 保留在内存中直到heavy_window 未被清空是正确的吗?
    • 将闭包内的object var 清零可以帮助gc 吗?
  • 案例 2:

    • 以这种方式命名闭包...addEventListener(callback = function() {}) 而不是...addEventListener(function callback() {}) 会导致内存泄漏?声明callback = function() {}会导致全局隐藏变量?

注意,我不需要 jQuery 中的示例或使用其他框架。我有兴趣了解更多关于 JavaScript vanilla 的信息。

提前谢谢你。

【问题讨论】:

  • 关于案例一,你觉得object和heavy_window有什么关系?
  • @Bergi heavy_window 是在附加到object 的侦听器中创建的,所以.. 直到heavy_window 存在,object 仍保留在内存中。我说的对吗?
  • 没有。侦听器函数可能附加到object,但在调用期间创建的东西不是。当函数返回时,它们会超出范围,并且不会保留对它们的引用。除非您将它们显式存储在某个地方,或者可能从函数中 return 它们,以便调用者可以对它们做任何事情。

标签: javascript memory memory-management memory-leaks closures


【解决方案1】:

我认为 ES 规范中没有指定垃圾收集的细节。然而,在大多数解释器中,一旦不存在对对象的任何引用或不可访问,或在稍后时间安排,对象通常会被垃圾回收。

在情况 1 中,如果您将事件对象传递给 HeavyWindow,heavy_window 可能会访问原始的 new EventEmitter(event 通常会引用事件目标),因此您的 new EventEmitter() 可能不会被垃圾收集,直到所有对您的 heavy_window 的引用都消失了。如果没有,那么您的new EventEmitter 将在未来某个时候被垃圾收集。

在情况 2 中,将回调函数分配给全局变量 callback 不会改变任何内容,因为回调函数没有对您创建的实际 new EventEmitter 对象的任何引用。 (同样,除非event 引用了您创建的new EventEmitter 对象。)

实际上情况可能会有所不同,因为浏览器中的垃圾收集器相当复杂。解释器何时决定收集垃圾实际上取决于它,但底线是它只会在对对象的所有引用都消失时才会这样做。

内存管理通常不是 JavaScript 真正关心的问题,您大部分时间都不需要考虑它。如果存在内存泄漏,您将知道它并能够通过使用浏览器提供的开发者工具检测到它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 2011-01-25
    相关资源
    最近更新 更多