Javascript:命名关闭和内存管理

时间:2017-09-08 07:18:57

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

我试图更多地了解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
});

我的问题是:

  • 案例1:

    • object未被清空之前,heavy_window是否仍在记忆中是否正确?
    • 在封闭内部取消object var可以帮助gc?
  • 案例2:

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

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

提前谢谢。

1 个答案:

答案 0 :(得分:0)

我不认为垃圾收集的细节在ES规范中有详细说明。但是,在大多数解释器中,一旦对象没有任何对该对象的引用或者无法访问或者在以后安排,对象通常会被垃圾收集。

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

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

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

内存管理通常不是JavaScript的问题,你不应该在大多数时候考虑它。如果存在内存泄漏并且能够使用浏览器提供的开发人员工具检测到它,您将会知道它。