JavaScriptのMap
は、キーと値のペアを保持するための便利なデータ構造です。
しかし、キーとしてオブジェクトを使用する場合には注意が必要です。
以下のコードがundefined
を出力する理由とその対策について説明します。
const map = new Map();
map.set({a: 1}, "foo");
console.log(map.get({a: 1})); // "undefined"と表示される
問題の原因
上記のコードでは、mapにオブジェクト{a: 1}
をキーとして値foo
をセットしています。
同じ形状のオブジェクト{a: 1}
を使って値を取得しようとすると、undefined
が表示されます。
これは、JavaScriptではオブジェクトが参照によって比較されるためです。map.set
で使用したオブジェクトとmap.get
で使用したオブジェクトは異なるメモリ参照を持つため、同じキーとは認識されません。
解決方法
この問題を解決するための方法をいくつか紹介します。
1. 同じオブジェクト参照を使用する
const map = new Map();
const key = {a: 1};
map.set(key, "foo");
console.log(map.get(key)); // "foo"と表示される
同じオブジェクト参照を使用することで、期待通りの結果が得られます。
2. プリミティブ値をキーとして使用する
const map = new Map();
const key = JSON.stringify({a: 1});
map.set(key, "foo");
console.log(map.get(JSON.stringify({a: 1}))); // "foo"と表示される
オブジェクトを文字列に変換してキーとして使用します。同じ構造のオブジェクトは同じ文字列になるため、意図した通りに動作します。
3. WeakMapの使用
const map = new WeakMap();
const key = {a: 1};
map.set(key, "foo");
console.log(map.get(key)); // "foo"と表示される
WeakMap
を使用することで、オブジェクトがガベージコレクションの対象になります。キーとしてオブジェクトを使用し、同じ参照を保持する場合に有効です。
以上が解決方法となります。
最後に
実装でハマってしまい、学んだはいいものの、すぐに忘れてしまいそうなので記事に残しました。