JavaScriptのWeakRefで効率的なガベージコレクションを管理する

JavaScriptのWeakRefで効率的なガベージコレクションを管理する

WeakRefは、オブジェクトへの参照をガベージコレクタの影響を受けやすい形で保持するための機能です。本記事では、WeakRefを利用して効率的にメモリ管理を行う方法を学びます。

WeakRefとは

WeakRefは、JavaScriptで導入されたオブジェクト参照の一種で、通常の参照とは異なり、ガベージコレクタによって対象が解放されることを防ぎません。

WeakRefの基本的な使い方

const obj = { data: 'example' };
const weakRef = new WeakRef(obj);

console.log(weakRef.deref()); // { data: 'example' }

derefメソッド

derefメソッドは、WeakRefが保持するオブジェクトを取得するために使用します。

const retrieved = weakRef.deref();
if (retrieved) {
  console.log('Object is still alive:', retrieved);
} else {
  console.log('Object has been garbage collected');
}

WeakRefの活用例

WeakRefを使用して、キャッシュを構築する簡単な例です。

class Cache {
  constructor() {
    this.cache = new Map();
  }

  add(key, value) {
    this.cache.set(key, new WeakRef(value));
  }

  get(key) {
    const ref = this.cache.get(key);
    if (!ref) return null;
    return ref.deref();
  }
}

// 使用例
const cache = new Cache();
const obj = { id: 1 };
cache.add('item1', obj);

console.log(cache.get('item1')); // { id: 1 }

WeakRefの利点

– メモリ効率の向上 – 不要なオブジェクトの解放を妨げない – キャッシュ管理の最適化

WeakRefの制約

– 確実にオブジェクトが存在することを保証しない – ガベージコレクタの動作に依存

ファイナライザ登録

WeakRefは通常FinalizationRegistryと組み合わせて使用します。

const registry = new FinalizationRegistry(key => {
  console.log(`Object associated with key ${key} was garbage collected`);
});

const obj = { data: 'important' };
registry.register(obj, 'someKey');

// オブジェクトがガベージコレクタに解放されると、コールバックが呼び出される

FinalizationRegistryの使用例

キャッシュとFinalizationRegistryを組み合わせた例です。

class EnhancedCache {
  constructor() {
    this.cache = new Map();
    this.registry = new FinalizationRegistry(key => {
      this.cache.delete(key);
      console.log(`Cache entry for ${key} was garbage collected`);
    });
  }

  add(key, value) {
    this.cache.set(key, new WeakRef(value));
    this.registry.register(value, key);
  }

  get(key) {
    const ref = this.cache.get(key);
    return ref ? ref.deref() : null;
  }
}

// 使用例
const enhancedCache = new EnhancedCache();
const obj = { id: 42 };
enhancedCache.add('item42', obj);

console.log(enhancedCache.get('item42')); // { id: 42 }
// objが解放されるとキャッシュも削除される

WeakRefのユースケース

– キャッシュの最適化 – 一時的なデータ構造 – 高頻度なリソース参照の削減

WeakRefを使う際の注意点

– ガベージコレクタの動作に依存しすぎない – 他のパターンで代替可能な場合は使用を避ける

WeakMapとの違い

WeakMapも同様にオブジェクトをキーにするデータ構造ですが、WeakRefは直接的な参照の削除に特化しています。

WeakRefが適する場面

– 長期間保持しないオブジェクト参照が必要な場合 – 明示的な解放が不要な場合

まとめ

WeakRefは、特定の状況で効率的なメモリ管理を可能にするツールです。正しく利用することで、アプリケーションのパフォーマンスを向上させることができます。