这个问题已经以多种不同的形式被问到,但我不确定我的情况是否完全适用。
比如说,我有一个 node.js 程序。我的程序通过实例化一个名为 Stream 的类来连接到 Stream。在 Stream 中,一个 StreamParser 类被实例化,其中包含几个定时器。
当我 Stream.destroy()
我的原始 Stream 时,保存 StreamParser 的对象被设置为 null
。内存空间会发生什么变化,定时器会发生什么变化?似乎我的计时器仍在运行,除非我明确地 clearTimeout
它们......
因此,嵌套结构:
new Stream()
-> this.stream = new StreamParser()
-> this.intv = setInterval(function() { // code }, 1000);
// Streams are destroyed like this:
Stream.destroy()
-> calls this.stream.destroy(function() {
self.stream = null;
// stream is null. but timers seem to be running. So, is stream still in memory?
}
我有点困惑。更扩展的代码示例:
// main call.
var stream = new Stream();
stream.connect();
setTimeout(function() {
stream.destroy(function() {
stream = null;
});
}, 60000);
/** ############# STREAM ############### **/
function Stream() {
this.stream = null;
this.end_callback = null;
}
Stream.prototype.connect = function() {
var self = this;
new StreamParser('stream.com', function(stream) {
self.stream = stream;
self.stream.on('destroy', function(resp) {
if(self.end_callback !== null && typeof self.end_callback === 'function') {
var fn = self.end_callback;
self.end_callback = null;
self.stream = null;
fn();
} else {
self.stream = null;
}
});
});
}
Stream.prototype.destroy = function(callback) {
this.end_callback = callback;
this.stream.destroy();
}
/** ############# STREAM PARSER ############### **/
function StreamParser(uri, callback) {
var self = this;
this.conn = null;
this.callback = null;
this.connectSocket(uri, function(conn) {
self.conn = conn;
self.callback(conn);
})
setInterval(function() {
self.checkHeartbeat();
}, 1000);
}
StreamParser.prototype.checkHeartbeat = function() {
// check if alive
}
StreamParser.prototype.destroy = function() {
this.conn.destroy();
this.emit('destroy', 'socket was destroyed');
}
最佳答案
在 javascript 中,您不会像在 C++ 等语言中那样显式销毁对象。相反,当您通过将变量设置为 null
来清除对该对象的引用时,这会使该对象更有资格进行垃圾回收(现在少了一段脚本来保存对该对象的引用) .但是,如果有任何其他对该对象的引用,那么它仍然不会被垃圾回收。
在这种情况下,您的计时器在它们的闭包(它们周围的函数)中持有对您的对象的引用,这意味着仍然存在对流的引用,因此它不会被垃圾收集器清除。系统会保留对您的计时器的引用,以便它们正常执行(无论您对流对象做什么)并且当它们触发时,它们将按照设计的方式对(仍然存在的)流对象进行操作。
如果你想停止定时器,那么你需要在它们上显式地使用 clearTimeout()
。这将导致包含对流对象的其他引用的计时器闭包随后被释放,如果代码中其他任何地方都没有对流对象的其他引用,则 javascript 垃圾收集器将能够实际释放流对象使用的内存。
当流对象最终被垃圾回收时,它会导致它对它引用的任何子对象的引用不再处于事件状态。如果这些对象本身在您的代码中的任何地方都没有其他引用指向它们,那么它们也将被垃圾收集。但是,如果其他一些代码也指向其中一个子对象,则该子对象将被保留以供其他引用使用。
关于Javascript:将类/对象引用设置为 NULL,内存中的子对象/类会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11932205/