0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人的アウトプットカレンダーAdvent Calendar 2024

Day 6

【JavaScript】WeakMap / WeakSet って何?

Last updated at Posted at 2024-12-05

先日、mapsetについて調べていると、WeakMap WeakSetというワードが出てきました。

今回はこの耳なじみがないWeakMap WeakSetについて調べてみました。

WeakMapについて

WeakMapとは

WeakMapとは何でしょうか。
お馴染みのMDNには下記のように記載されています。

WeakMap オブジェクトは、キーが弱く参照されるキーと値の組のコレクションです。キーはオブジェクトでなければならず、値は任意の値を取ることができます。

キーが弱く参照される」というのがキーワードですね。
では特徴を見ていきましょう。

WeakMapの特徴

  1. キーはオブジェクトのみ
    プリミティブ型は使用できません
  2. キーの弱い参照
    WeakMap 内のキーはほかに参照されていない場合、自動的にガーベジコレクションされ、メモリリークを防ぐことができる
  3. サイズやイテレーション不可
    WeakMap は内容を列挙することができない(for...ofsize プロパティを使用できない)

WeakMapの使用例

実際の使用例を見てみましょう

①プライベートデータの隠蔽
オブジェクトキーを持っていないとデータにアクセスすることができません。
これにより、プライベートデータを保存するのに役立ちます。

// WeakMapを使用してオブジェクトのプライベートデータを管理
const privateData = new WeakMap();

class User {
  constructor(name) {
    // ユーザー情報をプライベートデータとして保存
    privateData.set(this, { name });
  }

  getName() {
    // プライベートデータにアクセス
    return privateData.get(this).name;
  }
}

const user = new User('Alice');
console.log(user.getName()); // "Alice"

// オブジェクトを知っている場合のみアクセス可能
console.log(privateData.get(user)); // { name: "Alice" }

// 直接全体を見る手段がない(列挙不可)
console.log([...privateData]); // TypeError: privateData is not iterable


②DOM要素に関連データを紐づける
DOM要素が削除されると、その要素に紐づけられていたデータもメモリから解放されます。
これによりメモリリークを防止できます。

// DOM要素に関連するデータを管理
const elementData = new WeakMap();

const button = document.createElement('button');
elementData.set(button, { clicked: 0 });

button.addEventListener('click', () => {
  // ボタンがクリックされた回数を記録
  const data = elementData.get(button);
  data.clicked++;
  console.log(`Button clicked ${data.clicked} times`);
});

document.body.appendChild(button);

// 5秒後にボタンを削除
// ボタンが削除されると関連データも自動的にガベージコレクションされる
setTimeout(() => {
  document.body.removeChild(button);
  console.log('Button removed from DOM');
}, 5000);

WeakMapのメリット

WeakMap には以下のメリットがあるようです。

  • 自動的なメモリ解放でメモリリークを防止
  • プライベートデータの安全な管理

WeakSetについて

WeakSetとは

MDNには下記のように記載されています。

WeakSet オブジェクトは、コレクションに弱く参照されたオブジェクトを格納することができます。

弱く参照されたオブジェクト」というのがキーワードですね。
では特徴を見ていきましょう。

WeakSetの特徴

  1. オブジェクトのみを格納可能
    プリミティブ型は格納できません
  2. 弱い参照を持つ
    WeakSet に追加されたオブジェクトがほかの場所で参照されなくなると、自動的にガーベッジコレクションの対象になります
  3. イテレーション不可
    通常の Set とは異なり、WeakSet の内容を列挙したり取得することはできません

基本的に WeakMap の特徴と同じですね。

WeakSetの使用例

こちらも実際の使用例を見てみましょう

①DOM要素の追跡
WeakSet を使ってすでに処理済みのDOM要素を追跡します。
ボタンが削除されると、自動的に WeakSet からも削除されます。

// WeakSetを作成
const processedElements = new WeakSet();

const button1 = document.createElement('button');
const button2 = document.createElement('button');

button1.textContent = 'Button 1';
button2.textContent = 'Button 2';

document.body.appendChild(button1);
document.body.appendChild(button2);

// イベントリスナーで処理済み要素を追跡
button1.addEventListener('click', () => {
  if (!processedElements.has(button1)) {
    console.log('Button 1 clicked for the first time!');
    processedElements.add(button1); // 処理済みに追加
  } else {
    console.log('Button 1 was already processed.');
  }
});

button2.addEventListener('click', () => {
  if (!processedElements.has(button2)) {
    console.log('Button 2 clicked for the first time!');
    processedElements.add(button2);
  } else {
    console.log('Button 2 was already processed.');
  }
});


②オブジェクトの一時的な記録
特定の状態のオブジェクトを一時的に追跡する場合に使用できます。

// WeakSetを作成
const visitedPlayers = new WeakSet();

// プレイヤーオブジェクト
const player1 = { name: 'Kenny' };
const player2 = { name: 'Bob' };

// プレイヤーがエリアを訪れた場合に記録
function visitArea(player) {
  if (visitedPlayers.has(player)) {
    console.log(`${player.name} has already visited this area.`);
  } else {
    console.log(`${player.name} visits the area for the first time.`);
    visitedPlayers.add(player);
  }
}

visitArea(player1); // Kenny visits the area for the first time.
visitArea(player2); // Bob visits the area for the first time.
visitArea(player1); // Kenny has already visited this area.

WeakSetのメリット

WeakSet には以下のようなメリットがあるようです。

  • 自動的なメモリ解放でメモリリークを防止
  • データの隠蔽やセキュリティの向上

まとめ

WeakMap / WeakSet どちらも大きなメリットは、
自動的にメモリが解放される点です。

そのため、一時的に使用する情報を保持する際に最も役立つのかなと思いました。

それでは。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?