JavaScript | 第11章「キー付きコレクション」

javascrpit JavaScript
スポンサーリンク

JavaScript「キー付きコレクション」完全入門(初心者向け)

初心者が 「Map / WeakMap / Set / WeakSet をどう使えばいいか」 を感覚的に理解できるように、実例・用途・注意点つきで詳しく説明します。

まず全体像をざっくりつかもう!

コレクション目的キー or 値の型重複反復できる?弱参照?
Mapキーと値を対応づける何でもOK(オブジェクトもOK)キー重複なし✅できる❌しない
WeakMapオブジェクトに秘密データをひもづけるオブジェクトのみキー重複なし❌できない✅する
Set重複のない値の集まり何でもOK値重複なし✅できる❌しない
WeakSetオブジェクトの一時マークオブジェクトのみ値重複なし❌できない✅する

1. Map:連想配列の進化版

どんなとき使う?

  • 文字列以外(オブジェクトなど)をキーにしたいとき
  • データの登録・削除・存在確認を頻繁にする場合
  • 要素を追加した順に処理したいとき

例:ユーザー情報を管理する

const userData = new Map();

const user1 = { name: "Alice" };
const user2 = { name: "Bob" };

userData.set(user1, { score: 80 });
userData.set(user2, { score: 95 });

console.log(userData.get(user1)); // { score: 80 }

for (const [user, info] of userData) {
  console.log(`${user.name}: ${info.score}`);
}
// 出力順(挿入順)
// Alice: 80
// Bob: 95
JavaScript

よく使うメソッド

メソッド説明
.set(key, value)値を登録する
.get(key)値を取り出す
.has(key)登録されているか確認
.delete(key)削除する
.clear()全削除
.size登録数を取得

Objectとの違いまとめ

比較点ObjectMap
キーの型文字列 or シンボル何でもOK(オブジェクト、配列など)
登録順序保証されない保証される
要素数Object.keys(obj).lengthmap.size
反復方法for...in(注意点多い)for...of, map.forEach()
主な用途静的データ定義動的なキー値ペア管理

2. WeakMap:オブジェクト専用の「秘密の倉庫」

どんなとき使う?

  • オブジェクトに プライベートデータ を持たせたい
  • オブジェクトが削除されたら、自動で関連データも消えてほしい

例:プライベート情報の隠し場所

const privateData = new WeakMap();

class User {
  constructor(name, secret) {
    this.name = name;
    privateData.set(this, { secret });
  }

  reveal() {
    console.log(`${this.name}の秘密は:`, privateData.get(this).secret);
  }
}

const alice = new User("Alice", "🍰が好き");
alice.reveal(); // Aliceの秘密は: 🍰が好き

// alice がメモリから消えたら WeakMap の中身も自動で破棄される
JavaScript

⚠️ 注意!

  • WeakMapキーがオブジェクトだけ
  • .sizefor...of が使えない(中身を一覧できない)。
  • 手動でクリアしなくても、ガベージコレクションで自動的に整理される。

3. Set:重複のない値のコレクション

どんなとき使う?

  • 配列から重複を除きたい
  • 「一度だけ登録したい」データを管理したい
  • 高速な「含まれているかチェック」が欲しい

例:重複を削除する

const numbers = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4]
JavaScript

例:参加ユーザー管理

const participants = new Set();

participants.add("Alice");
participants.add("Bob");
participants.add("Alice"); // 重複は無視される

console.log(participants.size); // 2

participants.delete("Bob");
console.log(participants.has("Alice")); // true
JavaScript

Set の便利テク

const setA = new Set([1, 2, 3]);
const setB = new Set([2, 3, 4]);

// 和集合(どちらかに含まれる)
const union = new Set([...setA, ...setB]); // {1,2,3,4}

// 積集合(両方に含まれる)
const intersection = new Set([...setA].filter(x => setB.has(x))); // {2,3}

// 差集合(AにあってBにない)
const difference = new Set([...setA].filter(x => !setB.has(x))); // {1}
JavaScript

4. WeakSet:オブジェクトを「一時的にマーク」

どんなとき使う?

  • オブジェクトを「もう処理した」と記録しておく
  • メモリ管理を気にせず一時的にフラグを付けたい

例:DOM要素を処理済みチェック

const processed = new WeakSet();

function handleElement(el) {
  if (processed.has(el)) return; // すでに処理済みならスキップ
  processed.add(el);

  console.log("処理:", el.tagName);
}

// 要素例
const div = document.createElement("div");
handleElement(div);
handleElement(div); // 2回目は無視される
JavaScript

⚠️ 注意!

  • WeakSet もオブジェクト専用。
  • 反復不可・.size なし。
  • 要素が他から参照されなくなれば自動的に破棄。

5. パフォーマンス面の目安

操作Map / SetObject / Array
挿入速い(O(1))Array は O(n) になる場合も
検索速い(O(1))Array は O(n)
削除速い(O(1))Array は O(n)
順序保持✅あり❌不定(Object)

💡 結論:
「キーや値を高速に探したい/消したい/順序も保ちたい」ときは
Map / Set を使うのが正解!

6. SameValueZeroとは?(NaNが扱える理由)

通常の === 比較だと:

NaN === NaN // false
JavaScript

でも MapSet の内部ルール(SameValueZero)では:

const s = new Set([NaN]);
console.log(s.has(NaN)); // true!
JavaScript

つまり、NaN はちゃんと「同じもの」として扱われます。
+0-0 も同じ値として扱われます。

まとめ

用途使うべき構造
文字列以外のキーで値を管理したいMap
オブジェクトごとの秘密情報を安全に保持したいWeakMap
重複しない値のリストを管理したいSet
オブジェクトを一時的に「処理済み」などでマークしたいWeakSet
タイトルとURLをコピーしました