2

オブジェクトインスタンスを適切に「クリア」する方法を知りたいです。以下のコードでは、インスタンスが親によって「クリア」された後でも、内部の setInterval() が引き続き実行されます。

// simple Class
var aClass = function(){
    return {
        init: function(){
            console.log("aClass init()")
            setInterval( this.tick, 1000 );
            // note: we're not storing the ref
        },
        tick: function(){
            console.log("aClass tick");
        }
    }
}

// instantiate the class
var inst = new aClass();
inst.init();


// try to forget the instance
function test(){
    console.log("test() 1 inst:", inst);

    inst = null;

    console.log("test() 2 inst:", inst);
}

// run for a while, then call test()
setTimeout( test, 4000 );

出力:

aClass init()
aClass tick
aClass tick
aClass tick
test() 1 inst: {.....}
test() 2 inst: null
aClass tick
aClass tick ...

問題は、「aClass tick」メッセージが test() の後に出力され続けることです。

アイデア?

4

4 に答える 4

3

渡した関数がメモリsetIntervalに保持されており、それへの参照があるため、インスタンスはメモリに保持されています。この関数は、ブラウザのアクティブなインターバル タイマーのリストによって参照されます。

間隔ハンドルを覚えておく必要があります。

this.intervalHandle = setInterval( this.tick, 1000 );

...その後、 への参照をドロップするときに、次のinstように伝えたいと思うでしょう:

inst.cleanup();
inst = null;

...そしてinst.cleanup:

clearInterval(this.intervalHandle);

そうすれば、ブラウザーは に渡した関数への参照を削除しますsetInterval。つまり、その関数はガベージ コレクションの対象になります (コードに基づいて、それに対する他の参照はありません)。これは、インスタンスへの参照が解放されたことを意味します。したがって、そのインスタンスへの未解決の参照が他に存在しない場合は、ガベージ コレクションの対象となります。

于 2013-01-20T00:37:30.263 に答える
2

clearInterval()参照を削除しようとするのではなく、使用する必要があります。これは以前に回答されています - JavaScript での setInterval 呼び出しの停止を参照してください

于 2013-01-20T00:35:39.143 に答える
0

私の推測では、aClass のインスタンスにアクセスする方法がないため、aClass のインスタンスはなくなっていると思いますが、init では、setinterval のパラメーターとして使用すると tick 関数がコピーされます。

var tickfunction=null;
var aClass = function(){
    return {
        init: function(){
            console.log("aClass init()")
            tickfunction = this.tick;
        },
        tick: function(){
            console.log("aClass tick");
        }
    }
}

// instantiate the class
var inst = new aClass();
inst.init();

// try to forget the instance
console.log("test() 1 inst:", inst);
inst = null;
console.log("test() 2 inst:", inst);// its null isn't it?
console.log("the tickfunction:",tickfunction);

関数がコピーされることを示すには、次のようにします。

function toInterval(){
    console.log("orig");
}
setInterval(toInterval,1000);//prints orig every second
toInterval=function(){
    console.log("changed it");
}
toInterval();//prints changed it
于 2013-01-20T03:03:00.680 に答える
0

これは、ブラウザ自体setIntervalがおよび でスケジュールされたすべての機能を追跡するためsetTimeoutです。(そうしないと、関数を自分でどこかに保存する必要があり、ほとんどの場合かなり面倒です。) また、関数にはメソッドへの参照があるため、そのメソッドは存続します。しかし、それを証明するのは少し難しいですが、オブジェクトの残りの部分は捨てられたのではないかと思います。

そのような関数のスケジュールを解除する予定がある場合は、明示的に行う必要があります。

this.interval = setInterval(function, 4000);

// and then later, in some `destroy()` method
clearInterval(this.interval);

ところで、コンストラクターからそのような大きなハッシュを返す必要はほとんどありません。代わりにプロトタイプを使用します。

var SomeClass = function() {
    // ...
};

SomeClass.prototype.method = function() {
    console.log('hello from', this);
};
于 2013-01-20T00:39:50.080 に答える