2012-08-13 60 views
1

此問題已以多種不同形式提出,但我不確定我的情況是否完全適用。Javascript:將類/對象引用設置爲NULL,內存中的子對象/類會發生什麼?

說,我有一個node.js程序。我的程序通過實例化一個名爲Stream的類來連接到Stream。在Stream中,StreamParser類被實例化,其中包含幾個定時器。

當我I Stream.destroy()我的原始流,保存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'); 
} 

回答

3

在javascript中,您不會像使用C++這樣的語言顯式銷燬對象。相反,當您通過將變量設置爲null來清除對該對象的引用時,該對象使得該對象更有資格進行垃圾回收(現在只有一條腳本可以保存對該對象的引用)。但是,如果有任何其他對象的引用,那麼它仍然不會被垃圾收集。

在這種情況下,你的定時器在它們的閉包(它們周圍的函數)中持有對你的對象的引用,這意味着仍然有對流的引用,所以它不會被垃圾收集器清理。系統爲你的定時器提供了一個參考,它們將正常執行(不管你如何處理流對象),當它們觸發時,它們將按照它們設計的那樣操作(仍然存在)流對象。

如果您想停止計時器,那麼您需要在其上明確使用clearTimeout()。這將導致包含對流對象的其他引用的計時器閉包被釋放,並且如果在代碼中的其他任何地方沒有其他對流對象的引用,那麼JavaScript垃圾回收器將能夠實際釋放內存使用的流對象。

當流對象最終被垃圾回收時,它將引起它引用它引用的任何子對象不再處於活動狀態。如果這些對象本身在代碼中沒有其他引用指向它們,那麼它們也將被垃圾收集。但是,如果其他代碼也指向其中一個子對象,則該子對象將被保留用於其他引用。

2

JavaScript使用垃圾收集,這意味着任何對象,沒有人能夠達到再被「遺忘」。它不是「刪除」 - 沒有對該對象執行額外的操作。相反,它佔用的內存將再次可用來創建新的對象。

所以你需要問這個問題:任何人都可以看到孩子嗎?

在定時器的情況下,瀏覽器需要以某種方式執行它們,所以它必須有一個列表。這意味着有兩個引用計時器的地方:您的代碼和瀏覽器中的某個地方。如果你忘記了你的對象,只要它需要定時器,瀏覽器仍然保持其引用。

相關問題