Nodejs对象释放的问题

Nodejs对象释放的问题

 “use strict”

var util = require(“util”)

var Notifier = function() { var self = this setInterval(function(){ console.log(“emit”) },1000) }

var test = {}

test.n = new Notifier()

setTimeout(function(){ console.log(“quit”) delete test.n },5000)

按照我理解,5s后test.n对象被释放,也不会一直输出"emit",但是实际不是的,特此请教


6 回复

在 Node.js 中,对象的垃圾回收机制是由 V8 引擎自动管理的。当你使用 delete 操作符删除一个对象属性时,并不意味着立即释放该对象。V8 引擎会在适当的时候进行垃圾回收,这取决于对象是否仍然被其他地方引用。

在你的例子中,Notifier 对象有一个定时器(通过 setInterval 创建),这个定时器会不断执行回调函数,导致 Notifier 对象持续存在。即使你使用 delete 删除了 test.n 属性,只要定时器还在运行,Notifier 对象就不会被垃圾回收。

示例代码解析

"use strict";

var util = require("util");

var Notifier = function() {
    var self = this;
    setInterval(function(){
        console.log("emit");
    }, 1000);
};

var test = {};

test.n = new Notifier();

setTimeout(function(){
    console.log("quit");
    delete test.n;
}, 5000);

在这段代码中:

  1. Notifier 构造函数创建了一个 setInterval 定时器,每秒输出一次 "emit"
  2. test.n 被设置为一个新的 Notifier 实例。
  3. 5 秒后,test.n 被删除。

尽管 test.n 被删除了,但由于定时器仍然在运行,Notifier 实例不会被垃圾回收。因此,定时器会继续执行,输出 "emit"

如何解决这个问题?

如果你想在删除 test.n 后停止定时器,可以在 Notifier 构造函数中添加一个方法来清除定时器:

"use strict";

var util = require("util");

var Notifier = function() {
    var self = this;
    self.timerId = setInterval(function(){
        console.log("emit");
    }, 1000);

    // 添加一个方法来清除定时器
    self.stop = function() {
        clearInterval(self.timerId);
    };
};

var test = {};

test.n = new Notifier();

setTimeout(function(){
    console.log("quit");
    if (test.n) {
        test.n.stop(); // 停止定时器
        delete test.n; // 删除引用
    }
}, 5000);

在这个修改后的版本中,我们添加了一个 stop 方法来清除定时器。在删除 test.n 之前,调用 stop 方法来停止定时器。这样可以确保定时器在不再需要时被正确地清理,从而避免内存泄漏。


IntervalTimer不存在於那個對象裡。釋放這個對象,不會對timer有影響。

delete test.n只是从test的scope中移除对前面那个interval的引用n。真正的interval还存在内存当中。interval对象是这样销毁的:

var ref = setInterval();
clearInterval(ref);

在内存中该对象并未销毁~

delete test.n 只是销毁了n属性链接, 并没有销毁 Notifier 实例, setInterval 持有了这个实例的引用

在 Node.js 中,垃圾回收机制会自动管理内存的分配和释放。然而,如果你的对象仍然被其他地方引用,即使你认为它应该被释放,垃圾回收器也不会回收它。

在你的例子中,setInterval 创建了一个定时器,并且该定时器函数内部有一个对 self 的引用。即使你删除了 test.n,定时器依然持有对 Notifier 实例的引用,所以实例不会被垃圾回收。

要解决这个问题,你可以显式地停止定时器。例如,你可以使用 clearInterval 方法来清除定时器:

"use strict";

var util = require("util");

var Notifier = function() {
    var self = this;
    self.timerId = setInterval(function() {
        console.log("emit");
    }, 1000);
};

var test = {};

test.n = new Notifier();

setTimeout(function() {
    console.log("quit");
    clearInterval(test.n.timerId); // 清除定时器
    delete test.n;
}, 5000);

在这个修改后的版本中,Notifier 构造函数创建了一个定时器,并将其 ID 存储在 self.timerId 属性中。在 setTimeout 回调中,我们使用 clearInterval 来清除定时器,然后再删除 test.n 对象。这样可以确保定时器不再运行,并且对象可以被垃圾回收。

回到顶部