JavaScriptで「弱い参照」を作成することは可能ですか?


97

JavaScriptで別のオブジェクトへの「弱い参照」を作成する方法はありますか?弱い参照とは何かを説明したwikiページです。 Javaでそれらを説明する別の記事を次に示します。誰もがこの動作をJavaScriptで実装する方法を考えることができますか?


4
弱い参照はES6で議論されています。目をむいてください。
Ryan Smith

2
で*公式スペックウィキ/議論wiki.ecmascript.org/doku.php?id=strawman:weak_refs、現在「最終更新日:2013年2月2日22時25分」で、*他のいくつかのスペック議論esdiscuss.org/topic/what -is-the-status-of-weak-references、現在最後の投稿「Sun Mar 3 11:56:05 PST 2013」
Destiny Architect

ほとんどの場合、WRは、ここで説明されている、失効したリスナーの問題を解決するための試みです:[ stackoverflow.com/questions/43758217/…。その質問に良い答えがあった場合、WRの必要性はそれほど高くないと思います。
James

回答:


39

JavaScriptのweakrefの言語サポートはありません。手動の参照カウントを使用して独自にローリングできますが、特にスムーズに行うことはできません。JavaScriptオブジェクトでは、ガベージコレクションのタイミングがわからないため、プロキシラッパーオブジェクトを作成することはできません。

したがって、「弱い参照」は、add-referenceメソッドとremove-referenceメソッドを使用した単純なルックアップのキー(例:整数)になり、手動で追跡される参照がなくなった場合、エントリを削除して、今後のルックアップを残すことができます。 nullを返すキー。

これは実際には弱参照ではありませんが、同じ問題のいくつかを解決できます。DOMノードまたはイベントハンドラーとクロージャーなどのそれに関連付けられたオブジェクトの間に参照ループがある場合、ブラウザー(通常はIE、特に古いバージョン)からのメモリリークを防ぐために、通常は複雑なWebアプリケーションで行われます。これらの場合、完全な参照カウントスキームは必要ないかもしれません。


2
私はコードを注意深く調査(または使用)していませんが、es-labには基本的なWeakMapエミュレーションを提供するスクリプトがあります。Aurora 6(Mozilla)には、非標準のWeakMap実装があります。
theazureshadow

2
ES6では、この答えは正しくありません。下記の私の答えを参照してくださいstackoverflow.com/a/28567560/745190
thelastshadow

9
ES6 WeakMapsは本当の弱参照ではないため、それはまだ正しいです。WeakMapはオブジェクトをキーとしてのみ受け入れ、これらのオブジェクトへの参照は弱く保持されます。stackoverflow.com/questions/32397729/…を
CodeManX

私は弱いマップをエミュレートするクラスを作成して、ここに投稿しました:stackoverflow.com/a/47017206/491553
Ryan Shillington


11

更新:2019年9月

まだ弱い参照を使用することはできませんが、JavaScriptのWeakRefが作業中のため、おそらくすぐに使用できるようになります。詳細は以下。

提案

提案は現在ステージ3にあります。つまり、完全な仕様があり、さらに改良するには実装とユーザーからのフィードバックが必要です。

WeakRefの提案は、機能の二つの主要な新しい作品を包含する。

  • WeakRefクラスを使用したオブジェクトへの弱参照の作成
  • FinalizationGroupクラスを使用して、オブジェクトがガベージコレクションされた後にユーザー定義のファイナライザーを実行する

ユースケース

主な用途弱参照のためには、それはキャッシュやマッピングに表示されますので、大きなオブジェクトを単独で生かされていないことが望ましいのWHERE、大きなオブジェクトを保持するキャッシュやマッピングを実装することです。

ファイナライズとは、プログラムの実行に到達できなくなったオブジェクトの後にクリーンアップするコードを実行することです。ユーザー定義のファイナライザは、いくつかの新しい使用例を可能にし、ガベージコレクタが認識していないリソースを管理する際のメモリリークの防止に役立ちます。

出典および参考文献

https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references


1
Firefox NightlyはWeakRefの実験的サポートを追加しました。これを使用して、反復可能なバージョンのWeakSetを作成する実装例を次に示します。gist.github.com/ seanlinsley
seanlinsley

3

真の弱い参照、いいえ、まだです(ただし、ブラウザメーカーはこの問題を検討しています)。しかし、これは弱参照をシミュレートする方法に関するアイデアです。

オブジェクトをドライブするキャッシュを構築できます。オブジェクトが格納されると、キャッシュはオブジェクトが使用するメモリ量の予測を保持します。画像の保存など一部のアイテムでは、これは簡単に解決できます。他の人にとって、これはもっと難しいでしょう。

オブジェクトが必要なときは、キャッシュにそれを要求します。キャッシュにオブジェクトがある場合は、それが返されます。存在しない場合は、アイテムが生成、保存されてから返されます。

予測メモリの総量が特定のレベルに達すると、アイテムを削除するキャッシュによって弱参照がシミュレートされます。アイテムが取り出された頻度に基づいて、アイテムが取得された頻度に基づいて、最も使用されていないアイテムを予測します。アイテムを作成するコードがクロージャーとしてキャッシュに渡される場合、「計算」コストも追加される可能性があります。これにより、構築または生成に非常にコストのかかるアイテムをキャッシュが保持できるようになります。

これを間違えると、最も人気のあるアイテムを削除してしまう可能性があるため、削除アルゴリズムは重要です。これはひどいパフォーマンスを引き起こします。

キャッシュが、保存されたオブジェクトへの永続的な参照を持つ唯一のオブジェクトである限り、上記のシステムは、真の弱い参照の代替としてかなりうまく機能するはずです。


25
あなたが言ったことのほとんどはweakrefと無関係ではありませんか?
Erik Kaplun

22
@ JL235-弱参照の重要な用途は、キャッシュではなくイベントハンドラーです。存在している間、他のイベントを監視する必要があるオブジェクトがありますが、それが通知リストに含まれているという事実がGCの目的で参照を構成することを望んでいません。
Malvolio、2012年

7
弱い参照はキャッシングとは関係ありません。弱い参照は、何かを追跡する必要があることを意味しますが、追跡されているオブジェクトへの参照が残っていない場合は、削除することを許可します。
fabspro 2013年

8
自動有効期限のために弱い参照を使用してキャッシュを構築する使用例があることは明らかです。
Phil Freeman

5
キャッシュは、弱参照の伝統的な最大の理由です。イベントハンドラーのDOMは、IEエクスプローラーのバグの一部にすぎません。
axkibe 2013


2

JL235上記で提案したように、キャッシングメカニズムを使用して弱い参照をエミュレートすることは合理的です。弱参照がネイティブに存在する場合、次のような動作が見られます。

this.val = {};
this.ref = new WeakReference(this.val);
...
this.ref.get(); // always returns val
...
this.val = null; // no more references
...
this.ref.get(); // may still return val, depending on already gc'd or not

一方、キャッシュを使用すると、次のことがわかります。

this.val = {};
this.key = cache.put(this.val);
...
cache.get(this.key); // returns val, until evicted by other cache puts
...
this.val = null; // no more references
...
cache.get(this.key); // returns val, until evicted by other cache puts

参照の保持者として、値を参照するときについて何も仮定しないでください。これは、キャッシュを使用しても違いはありません。



-4

EcmaScript 6(ES Harmony)にはWeakMapオブジェクトがあります。最新のブラウザーでのブラウザーのサポートはかなり良好です(Firefoxの最後の3つのバージョン、クロム、および今後のIEバージョンでさえサポートされています)。


29
これはまったく同じではありません。A WeakMapはオブジェクトへの弱参照を与えません-WeakMapで弱参照であるのはではなく、キーです。弱い参照がマップに存在するという事実は、メモリリークを防止するメカニズムにすぎず、それ以外の場合はユーザーが監視できません。
EyasSH 2015年

1
弱いのは値ではなくキーであるということは正しいです。ただし、弱参照を使用する目的は、参照されるオブジェクトのガベージコレクションを許可することです。OPは2つのリンクを投稿しました。2番目のリンクは、拡張できないオブジェクトにIDを追加することです。実際、JavaScriptのWeakMapに相当するJavaのWeakHashMapを使用することをお勧めします。
thelastshadow 2015年

12
以来、弱参照実装にWeakMapを使用して幸運weakmap.get(new String('any possible key that has ever existed or ever will exist'))になる常にあることをundefined。 役に立たない。反対投票!
user3338098 2016年

-5

http://www.jibbering.com/faq/faq_notes/closures.html

ECMAScriptは自動ガベージコレクションを使用します。仕様では詳細が定義されておらず、実装者が整理する必要があります。一部の実装では、ガベージコレクション操作の優先度が非常に低いことが知られています。しかし、一般的な考え方は、オブジェクトが(コードの実行にアクセス可能なままにされたままの参照がなくなることによって)参照できなくなると、ガベージコレクションに使用できるようになり、ある時点で破棄され、消費しているリソースが解放されて返されるということです。システムに再利用します。

これは通常、実行コンテキストを終了するときに当てはまります。スコープチェーン構造、アクティベーション/変数オブジェクト、および実行コンテキスト内で作成されたオブジェクト(関数オブジェクトを含む)はアクセスできなくなり、ガベージコレクションに使用できるようになります。

弱いものはなく、もはや利用できなくなったものだけを意味します。


10
弱い参照を使用する理由は、参照サイクルの回避だけではありません。これらは、オブジェクトインスタンスのプール/キャッシングなどに非常に便利です。
フワフワした

WeakReferenceの定義は問題ではありません。上記のコメントにも同意します。
Yuri Yaryshev
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.