aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/javascript/reference/global_objects/weakref/index.html
blob: 08327348d74e02ce6ea565ac5bfccd47dd84cc55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
---
title: WeakRef
slug: Web/JavaScript/Reference/Global_Objects/WeakRef
tags:
  - Class
  - JavaScript
  - NeedsTranslation
  - Reference
  - TopicStub
  - WeakRef
translation_of: Web/JavaScript/Reference/Global_Objects/WeakRef
---
<div>{{JSRef}}</div>

<p><strong><code>WeakRef</code></strong> オブジェクトにより、ガベージコレクションが行われることを妨げない他のオブジェクトへの弱い参照を保持します。</p>

<h2 id="Description" name="Description">解説</h2>

<p><code>WeakRef</code> オブジェクトはオブジェクトへの弱い参照を含み、これは<em>ターゲット</em>または<em>リファレント</em>と呼ばれます。オブジェクトへの弱い参照は、ガベージコレクターによるオブジェクトの回収を妨げない参照です。対照的に、通常の (または<em>強い</em>) 参照はオブジェクトをメモリに保持します。オブジェクトが強い参照を持たなくなった場合、 JavaScript エンジンのガベージコレクターはオブジェクトを破棄してメモリを再取得することがあります。そうなると、弱い参照からオブジェクトを取得することはできなくなります。</p>

<div class="note">
<p><strong>注:</strong> 下記の<a href="#Avoid_where_possible">できる限り避ける</a>の節をご覧ください。正しい <code>WeakRef</code> の使用は注意深く考える必要があり、可能であれば避けるのが最良です。</p>
</div>

<h2 id="Constructor" name="Constructor">コンストラクター</h2>

<dl>
 <dt>{{jsxref("WeakRef/WeakRef", "WeakRef()")}}</dt>
 <dd>新しい <code>WeakRef</code> オブジェクトを生成します。</dd>
</dl>

<h2 id="Instance_methods" name="Instance_methods">インスタンスメソッド</h2>

<dl>
 <dt>{{jsxref("WeakRef.deref", "WeakRef.prototype.deref()")}}</dt>
 <dd><code>WeakRef</code> オブジェクトの対象オブジェクトを返すか、対象オブジェクトが既に回収されている場合は <code>undefined</code> を返します。</dd>
</dl>

<h2 id="Avoid_where_possible" name="Avoid_where_possible">可能な限り避ける</h2>

<p><code>WeakRef</code> の正しい使用には慎重な検討が必要であり、可能であれば避けた方が良いでしょう。また、仕様で保証されていない特定の動作に依存しないことも重要です。ガベージコレクションがいつ、どのように、そしてどのように発生するかは、使用している JavaScript エンジンの実装に依存します。あるエンジンで観察した動作が、別のエンジン、同じエンジンの別のバージョン、あるいは同じエンジンの同じバージョンでも少し違う状況では異なる可能性があります。ガベージコレクションは、 JavaScript エンジンの実装者が常に解決策を改良している難しい問題です。</p>

<p>ここでは、 WeakRef の提案の著者がその<a href="https://github.com/tc39/proposal-weakrefs/blob/master/README.md">説明文書</a>に盛り込んだ具体的なポイントをいくつか紹介します。</p>

<blockquote>
<p><a href="https://ja.wikipedia.org/wiki/%E3%82%AC%E3%83%99%E3%83%BC%E3%82%B8%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3">ガベージコレクション</a>は複雑です。アプリケーションもしくはライブラリが WeakRef のガベージコレクションの解放処理か、即時にファイナライザ (解放処理のコールバック) の呼出処理に依存している場合は、予想した動作とは異なる動作を行うかもしれません。解放処理は予想よりもかなり後に行われるか、もしくは行われないからです。以下に挙げた様々な原因が考えられます。</p>

<ul>
 <li>One object might be garbage-collected much sooner than another object, even if they become unreachable at the same time, e.g., due to generational collection.</li>
 <li>Garbage collection work can be split up over time using incremental and concurrent techniques.</li>
 <li>Various runtime heuristics can be used to balance memory usage, responsiveness.</li>
 <li>The JavaScript engine may hold references to things which look like they are unreachable (e.g., in closures, or inline caches).</li>
 <li>Different JavaScript engines may do these things differently, or the same engine may change its algorithms across versions.</li>
 <li>Complex factors may lead to objects being held alive for unexpected amounts of time, such as use with certain APIs.</li>
</ul>
</blockquote>

<h2 id="Notes_on_WeakRefs" name="Notes_on_WeakRefs">WeakRef における注意</h2>

<p>Some notes on <code>WeakRef</code>s:</p>

<ul>
 <li>If your code has just created a <code>WeakRef</code> for a target object, or has gotten a target object from a <code>WeakRef</code>'s <code>deref</code> method, that target object will not be reclaimed until the end of the current JavaScript <a href="https://tc39.es/ecma262/#job">job</a> (including any promise reaction jobs that run at the end of a script job). That is, you can only "see" an object get reclaimed between turns of the event loop. This is primarily to avoid making the behavior of any given JavaScript engine's garbage collector apparent in code — because if it were, people would write code relying on that behavior, which would break when the garbage collector's behavior changed. (Garbage collection is a hard problem; JavaScript engine implementers are constantly refining and improving how it works.)</li>
 <li>If multiple <code>WeakRef</code>s have the same target, they're consistent with one another. The result of calling <code>deref</code> on one of them will match the result of calling <code>deref</code> on another of them (in the same job), you won't get the target object from one of them but <code>undefined</code> from another.</li>
 <li>If the target of a <code>WeakRef</code> is also in a {{jsxref("FinalizationRegistry")}}, the <code>WeakRef</code>'s target is cleared at the same time or before any cleanup callback associated with the registry is called; if your cleanup callback calls <code>deref</code> on a <code>WeakRef</code> for the object, it will receive <code>undefined</code>.</li>
 <li>You cannot change the target of a <code>WeakRef</code>, it will always only ever be the original target object or <code>undefined</code> when that target has been reclaimed.</li>
 <li>A <code>WeakRef</code> might never return <code>undefined</code> from <code>deref</code>, even if nothing strongly holds the target, because the garbage collector may never decide to reclaim the object.</li>
</ul>

<h2 id="Example" name="Example"></h2>

<h3 id="Using_a_WeakRef_object" name="Using_a_WeakRef_object">WeakRef オブジェクトの使用</h3>

<p>This example starts a counter shown in a DOM element, stopping when the element doesn't exist anymore:</p>

<pre class="brush: js notranslate">class Counter {
  constructor(element) {
    // Remember a weak reference to the DOM element
    this.ref = new WeakRef(element);
    this.start();
  }

  start() {
    if (this.timer) {
      return;
    }

    this.count = 0;

    const tick = () =&gt; {
      // Get the element from the weak reference, if it still exists
      const element = this.ref.deref();
      if (element) {
        element.textContent = ++this.count;
      } else {
        // The element doesn't exist anymore
        console.log("The element is gone.");
        this.stop();
        this.ref = null;
      }
    };

    tick();
    this.timer = setInterval(tick, 1000);
  }

  stop() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = 0;
    }
  }
}

const counter = new Counter(document.getElementById("counter"));
counter.start();
setTimeout(() =&gt; {
  document.getElementById("counter").remove();
}, 5000);
</pre>

<h2 id="Specifications" name="Specifications">仕様書</h2>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">仕様書</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('WeakRefs', '#sec-weak-ref-objects', 'WeakRef')}}</td>
  </tr>
 </tbody>
</table>

<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2>

<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</div>

<p>{{Compat("javascript.builtins.WeakMap")}}</p>

<h2 id="See_also" name="See_also">関連情報</h2>

<ul>
 <li>{{jsxref("FinalizationRegistry")}}</li>
 <li>{{jsxref("WeakSet")}}</li>
 <li>{{jsxref("WeakMap")}}</li>
</ul>