1

この質問はさまざまな形式で尋ねられてきましたが、私の状況が完全に当てはまるかどうかはわかりません。

たとえば、node.js プログラムがあるとします。私のプログラムは、Stream というクラスをインスタンス化することにより、Stream に接続します。Stream 内で、StreamParser クラスがインスタンス化されます。これには、いくつかのタイマーが含まれます。

元の Stream の場合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');
}
4

2 に答える 2

3

javascriptでは、c++などの言語のようにオブジェクトを明示的に破棄することはありません。代わりに、変数をに設定してそのオブジェクトへの参照をクリアするとnull、オブジェクトがガベージコレクションの対象になります(オブジェクトへの参照を保持するスクリプトが1つ少なくなります)。ただし、オブジェクトへの他の参照がある場合でも、ガベージコレクションは行われません。

この場合、タイマーはオブジェクトへの参照をクロージャー(それらを囲む関数)に保持します。つまり、ストリームへの参照が残っているため、ガベージコレクターによってクリーンアップされません。システムはタイマーへの参照を維持し、タイマーが正常に実行され(ストリームオブジェクトで何をするかに関係なく)、タイマーが起動すると、設計どおりに(まだ存在する)ストリームオブジェクトを操作します。

タイマーを停止したい場合は、明示的に使用する必要がありclearTimeout()ます。これにより、ストリームオブジェクトへの他の参照を含むタイマークロージャが解放され、コード内の他の場所にストリームオブジェクトへの他の参照がない場合、javascriptガベージコレクターは実際に解放することができます。ストリームオブジェクトによって使用されるメモリ。

ストリームオブジェクトが最終的にガベージコレクションされると、参照している子オブジェクトへの参照がアクティブでなくなります。それらのオブジェクト自体に、それらを指すコード内の他の参照がない場合、それらもガベージコレクションされます。ただし、他のコードがそれらの子オブジェクトの1つを指している場合、子オブジェクトは他の参照用に保持されます。

于 2012-08-13T10:17:49.040 に答える
2

JavaScript はガベージ コレクションを使用します。つまり、誰もアクセスできなくなったオブジェクトはすべて「忘れられた」ものになります。「削除」ではありません。オブジェクトに対して実行される追加のアクションはありません。代わりに、それが占有するメモリが再び利用可能になり、新しいオブジェクトが作成されます。

ですから、この質問をする必要があります: まだ子供たちに会える人はいますか?

タイマーの場合、ブラウザは何らかの方法でそれらを実行する必要があるため、どこかにリストが必要です。これは、タイマーへの参照がある場所が2 つあることを意味します。コードとブラウザのどこかです。オブジェクトを忘れた場合でも、タイマーが必要な限り、ブラウザーはその参照を保持します。

于 2012-08-13T10:17:20.243 に答える