web-dev-qa-db-ja.com

JavaScript:クラスメソッドを介してクラスインスタンスを作成および破棄する

クラスメソッドを使用してオブジェクトを削除する方法を理解しようとしています。オブジェクトをメモリから解放するdestroyメソッドを持つクラスを作成できるようにしたいと思います。これまでのところ、私が行った研究は決定的ではありません。ガベージコレクションが最終的にオブジェクトを処理することは理解していますが、それを破壊するためのより確実な方法が欲しいのです。これは可能ですか?

// class constructor
var class = function () {
     this.destroy = function () {};
};

// instance
var instance = new class();
instance.destroy();
console.log(instance); // should be null or undefined
31
user699242

いいえ。JavaScriptは自動的にガベージコレクションされます。オブジェクトのメモリは、GCが実行を決定し、オブジェクトがコレクションに適格である場合にのみ回収されます。

それが必要に応じて自動的に行われるのを見て、明示的にメモリを回収する目的は何でしょうか?

18
Jon

1- JavaScriptでオブジェクトを実際に破棄する方法はありませんが、deleteを使用すると、オブジェクトから参照を削除できます。

var obj = {};
obj.mypointer = null;
delete obj.mypointer;

2- deleteキーワードに関する重要な点は、オブジェクトへの参照を削除した後、同じオブジェクトを指す他の参照がメモリに残っていない場合、実際にオブジェクトを破棄しないことです。オブジェクトは収集可能としてマークされます。 deleteキーワードは参照を削除しますが、実際のオブジェクトをGCしません。同じオブジェクトの複数の参照がある場合、すべてのポイントされた参照を削除した直後にオブジェクトが収集されます。

3-また、メモリリークを残さないようにしたい場合に役立ついくつかのトリックと回避策があります。たとえば、複数のオブジェクトを含む配列があり、それらのオブジェクトへの他のポイントされた参照がない場合、配列を再作成すると、それらのオブジェクトはすべて削除されます。たとえば、var array = [{}, {}]がある場合、array = []のような配列の値をオーバーライドすると、配列内の2つのオブジェクトへの参照が削除され、これら2つのオブジェクトは収集可能としてマークされます。

4-ソリューションの最も簡単な方法は次のとおりです。

var storage = {};
storage.instance = new Class();
//since 'storage.instance' is your only reference to the object, whenever you wanted to destroy do this:
storage.instance = null;
// OR
delete storage.instance;

前述のように、storage.instance = nullまたはdelete storage.instanceのいずれかを設定するだけで、オブジェクトへの参照を削除し、GCでクリーンアップできます。違いは、nullに設定した場合、ストレージオブジェクトにはインスタンスと呼ばれるプロパティがまだあるということです(値はnull)。 delete storage.instanceを使用すると、ストレージオブジェクトにはinstanceという名前のプロパティがなくなります。

およびdestroy methodについて??

ここでの逆説的な点は、破壊関数でinstance.destroyを使用すると、実際のinstanceポインターにアクセスできず、削除できないことです。

唯一の方法は、参照をdestroy関数に渡してから削除することです。

// Class constructor
var Class = function () {
     this.destroy = function (baseObject, refName) {
         delete baseObject[refName];
     };
};

// instanciate
var storage = {};
storage.instance = new Class();
storage.instance.destroy(object, "instance");
console.log(storage.instance); // now it is undefined

[〜#〜] but [〜#〜]もし私があなただったら、最初の解決策に固執し、次のようにオブジェクトを削除します。

storage.instance = null;
// OR
delete storage.instance;

うわー、多すぎた:)

41
Mehran Hatami

オブジェクトのプロパティは手動でのみ削除できます。副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:

var container = {};

container.instance = new class();

delete container.instance;

ただし、これは他のポインターでは機能しません。したがって:

var container = {};

container.instance = new class();

var pointer = container.instance;

delete pointer; // false ( ie attempt to delete failed )

さらに:

delete container.instance; // true ( ie attempt to delete succeeded, but... )

pointer; // class { destroy: function(){} }

したがって、実際には、削除はオブジェクトプロパティ自体を削除する場合にのみ有用であり、それらが指すコードをメモリから削除するための信頼できる方法ではありません。

手動で指定されたdestroyメソッドは、イベントリスナーのバインドを解除できます。何かのようなもの:

function class(){
  this.properties = { /**/ }

  function handler(){ /**/ }

  something.addEventListener( 'event', handler, false );

  this.destroy = function(){
    something.removeEventListener( 'event', handler );
  }
}
3
Barney

クラスインスタンスをメモリから削除するために見つけたメソッド:

var instance = new Class();
instance.__proto__ = null;
instance = null;
delete instance;
0
Bogdan