📝

君はJavaScriptのMapを知っているか?Mapの使い方・基本文法まとめ

2023/11/05に公開
2

こんにちは、AIQ株式会社のフロントエンドエンジニアのまさぴょんです!
今回は、JavaScriptのMapとは何か、Mapの使い方についてまとめて解説します。

JavaScriptのSetに関しては、こちらの記事で解説しています。
https://zenn.dev/aiq_dev/articles/2861af836f1f67

JavaScriptのMapとは何か?

Mapとは、keyvalueのペアを紐づけて(Mappingして)格納することのできるコレクションタイプのData型の1つです。

ObjectとMapの違いとは?

MapObjectと同じように、keyとそれに紐づいたvalueのデータの集まりです。
そんなMapObjectの違いは、どんな型のkeyも許可することです。

Objectでは、key名の設定には、制約がありますが、Mapでは、どんな型のDataでもkeyとして設定できます。

/** 1. Object の key名 の設定には、制約がある */
const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
  2000: 5000,
};
console.log("robotamaObject: ", robotamaObject);
// robotamaObject:  {2000: 5000, name: 'ロボ玉', like: 'ひまわりの種', power: 1000, hamflag: true}

/** 2. Map の key名には、どんな型の Data も設定できる */
const robotamaMap = new Map();
robotamaMap.set("ロボ玉", typeof "ロボ玉");
robotamaMap.set(12, typeof 12);
robotamaMap.set(true, typeof true);
robotamaMap.set([1, 2, 3], typeof [1, 2, 3]);
robotamaMap.set(robotamaObject, typeof robotamaObject);
console.log("robotamaMap: ", robotamaMap);
// robotamaMap:  Map(5) {'ロボ玉' => 'string', 12 => 'number', true => 'boolean', Array(3) => 'object', {…} => 'object'}

どんな時に、Mapを使用するのか? (Mapのユースケース)

それでは、Mapの使い所とは、どんな時でしょうか?
それは、keyに実際の変数Dataなどを使って、他のDataをMappingして管理したい場合などです。
(追記)
会社の先輩から教えていただき、ObjectとMapの使い分けのポイントとして、次のような点があるとのアドバイスをいただきました🌟

  1. Mapの方が、追加、削除、取得(find)がObjectよりも早くパフォーマンスがいい。
  2. Mapkeyの順番は、挿入順がそのまま列挙順となることが保証されている。
    • Objectの場合、keyの順番が列挙順で保証されているものと保証されていないものがある。
    • ゆえに、Objectで、列挙順に依存するコードを書くべきではない。

オブジェクト: 保証されることもあるが、混乱を招くので保証されないものとして扱うべきである。
Map: 挿入順。
引用元:[JavaScript] オブジェクト/Mapのキーの列挙順は保証されるのか

https://qiita.com/anqooqie/items/ab3fed5d269d278cdd2b

/** 1. DBから取得した UserDataList (ユーザーデータのリスト) */
const userList = [
  { id: 100, participant: "ロボたま", affiliation: "エンジニア" },
  { id: 101, participant: "まりぴょん", affiliation: "デザイナー" },
  { id: 102, participant: "白桃", affiliation: "営業部" },
];

/** 2. User id を key として、各Userごとの投稿・Data を管理する MapData */
const userPostListMap = new Map();

const userId_100 = userList[0].id;
const userId_101 = userList[1].id;
const userId_102 = userList[2].id;

/* 3-1. DBから取得した User id 100 の PostDataList (投稿データのリスト)  */
const postList_100 = [
  { id: 100, content: "Next.js 14系の最新情報まとめ" },
  { id: 100, content: "Vue3・Nuxt3系の学習" },
  { id: 100, content: "Knex.jsとDataStore" },
  { id: 100, content: "Software設計講座" },
];
// userId_100 を key として DBから取得した投稿データのリストをSetする
userPostListMap.set(userId_100, postList_100);

/* 3-2. DBから取得した User id 101 の PostDataList (投稿データのリスト)  */
const postList_101 = [
  { id: 101, content: "Figmaでのデザイン基礎講座" },
  { id: 101, content: "UI・UX向上のポイント" },
  { id: 101, content: "人を惹きつける、心地のいいデザイン" },
];

// userId_101 を key として DBから取得した投稿データのリストをSetする
userPostListMap.set(userId_101, postList_101);

/* 3-3. DBから取得した User id 102 の PostDataList (投稿データのリスト)  */
const postList_102 = [
  { id: 102, content: "Sassの売り込み方" },
  { id: 102, content: "関係性の作り方" },
  { id: 102, content: "飲みニケーション講座" },
];

// userId_102 を key として DBから取得した投稿データのリストをSetする
userPostListMap.set(userId_102, postList_102);

console.log("userPostListMap: ", userPostListMap);
// userPostListMap:  Map(3) {100 => Array(4), 101 => Array(3), 102 => Array(3)}

Mapの使い方・基本文法

ここからは、Mapの使い方・基本文法について解説していきます。
Mapの主なメソッドは次の通りです。

Mapの主なメソッド
  1. const map = new Map() – 新しいmapインスタンスを作ります。
  2. map.set(key, value)keyで、valueを格納します。
  3. map.get(key) – 指定されたkeyの値を返却します。mapに存在しないkeyの場合にはundefinedになります。
  4. map.has(key)keyが存在する場合にtrueを返します。そうでなければfalseになります。
  5. map.delete(key)keyで値を削除します。
  6. map.clear()mapをクリアします。
  7. map.size – 現在のmapインスタンスの要素の数です。

Mapの新規作成(初期インスタンスの作成)

Mapを新規作成する場合は、new Map()の形で、Mapインスタンスを作成します。
また[[key, value]](多重配列)の形で 初期値を渡すことができます。

/** 1. 空の Map Instance が作成される */
const map = new Map();
console.log("map", map); // map Map(0)

/**
 * 2. [[key, value]] (多重配列)の形で 初期値を渡すことができる
 * => 複数ある場合は、カンマ(,)区切り
 */
const map2 = new Map([
  ["key1", "value1"],
  ["key2", "value2"],
]);
console.log("map2", map2);
// map2 Map(2) {'key1' => 'value1', 'key2' => 'value2'}

Mapの長さ・sizeを測る

map.sizeで、Mapの長さ・sizeを測ることができます。

const map = new Map();
console.log("map", map); // map Map(0)
console.log("map.size", map.size); // 0

const map2 = new Map([
  ["key1", "value1"],
  ["key2", "value2"],
]);
console.log("map2", map2); 
// map2 Map(2) {'key1' => 'value1', 'key2' => 'value2'}
console.log("map2.size", map2.size); // 2

Mapに値(value)を追加する

map.set(key, value)の形で、Mapに値(value)を追加することができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const map = new Map();

// map.set(key, value) の形で、Mapに値(value)を追加する
map.set("robotama", robotamaObject);

Mapの値(value)を取得する

map.get(key)の形で、Mapの値(value)を取得することができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const map = new Map();

// map.set(key, value) の形で、Mapに値(value)を追加する
map.set("robotama", robotamaObject);

// map.get(key) の形で、Mapに値(value)を追加する
const robotama = map.get("robotama");

console.log(robotama);
// {name: 'ロボ玉', like: 'ひまわりの種', power: 1000, hamflag: true}

Mapにkeyが存在するかどうかを確認する

map.has(key)で、Mapkeyが存在するかどうかを確認することができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const map = new Map();

// map.set(key, value) で、Mapに値(value)を追加する
map.set("robotama", robotamaObject);

// map.has(key) で、Mapが key が存在するかどうかを確認する
const isRobotama = map.has("robotama");

isRobotama ? console.log("あり") : console.log("なし");

Mapにセットしたvalueを削除する

map.delete(key)で、Map内の値(value)を削除することができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const map = new Map();

// map.set(key, value) で、Mapに値(value)を追加する
map.set("robotama", robotamaObject);

// map.delete(key) で、値(value)を削除します
map.delete("robotama");
console.log(map);
// Map(0) {size: 0}

Map内のDataをclearする(すべて削除する)

map.clear()で、Map内の値(value)をすべて削除することができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map([
  ["robotama", robotamaObject],
  ["piui", piuiObject],
]);

console.log(map);
// Map(2) {'robotama' => {…}, 'piui' => {…}}

// map.clear() で、value をすべて削除する
map.clear();

console.log(map);
// Map(0) {size: 0}

Mapでの繰り返し処理

Mapには、ループ処理でDataを取り出すための3つのメソッドがあります。

Mapのループ処理メソッド
  1. map.forEach((value, key, map) => {})Mapから1つずつvaluekeyを取り出せます。
  2. map.keys()keyに対するiterableを返します。
  3. map.values()valueに対するiterableを返します。
  4. map.entries()[key, value] のiterableを返します。

Mapから1つずつvalutとkeyを取り出すforEach

map.forEach((value, key, map) => {})の形で、Mapから1つずつvaluekeyを取り出すことができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map();

map.set("robotama", robotamaObject).set("piui", piuiObject);
console.log("map: ", map);
// map:  Map(2) {'robotama' => {…}, 'piui' => {…}}

map.forEach((val, key, map) => {
  console.log("key: ", key);
  console.log("val: ", val);
});
// Map(2) {'robotama' => {…}, 'piui' => {…}}
// key:  robotama
// val:  {name: 'ロボ玉', like: 'ひまわりの種', power: 1000, hamflag: true}
// key:  piui
// val:  {name: 'ピウイ', like: 'ミルク', power: 5000, hamflag: false}

Mapのkeyを繰り返し処理する

map.keys()で、keyに対するiterable(反復可能Data)を取得できます。

イテラブルなので、for of文で取り出すことができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map();

map.set("robotama", robotamaObject).set("piui", piuiObject);
console.log("map: ", map);
// map:  Map(2) {'robotama' => {…}, 'piui' => {…}}

const mapKeys = map.keys();
console.log("mapKeys: ", mapKeys);
// mapKeys:  MapIterator {'robotama', 'piui'}

for (const key of mapKeys) {
  console.log("key: ", key);
}
// key:  robotama
// key:  piui

Mapのvalueを繰り返し処理する

map.values()で、valueに対するiterable(反復可能Data)を取得できます。

イテラブルなので、for of文で取り出すことができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map();

map.set("robotama", robotamaObject).set("piui", piuiObject);
console.log("map: ", map);
// map:  Map(2) {'robotama' => {…}, 'piui' => {…}}

const mapValues = map.values();
console.log("mapValues: ", mapValues);
// mapValues:  MapIterator {{…}, {…}}

for (const val of mapValues) {
  console.log("val: ", val);
}
// val:  {name: 'ロボ玉', like: 'ひまわりの種', power: 1000, hamflag: true}
// val:  {name: 'ピウイ', like: 'ミルク', power: 5000, hamflag: false}

Mapのkeyとvalueのセット(entry)を繰り返し処理する

map.entries()で、[key, value]iterable(反復可能Data)を取得できます。

イテラブルなので、for of文で取り出すことができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map();

map.set("robotama", robotamaObject).set("piui", piuiObject);
console.log("map: ", map);
// map:  Map(2) {'robotama' => {…}, 'piui' => {…}}

const mapEntries = map.entries();
console.log("mapEntries: ", mapEntries);
// mapEntries:  MapIterator {'robotama' => {…}, 'piui' => {…}}

for (const entry of mapEntries) {
  console.log("entry: ", entry);
}
// entry:  (2) ['robotama', {…}]
// entry:  (2) ['piui', {…}]

Mapから配列を生成する

Array.from()を使用することで、Mapから配列を生成することができます。

ちなみに、MapArray.from()で配列にすると、[key, value]の配列になります。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map();

map.set("robotama", robotamaObject).set("piui", piuiObject);
console.log("map: ", map);
// map:  Map(2) {'robotama' => {…}, 'piui' => {…}}

/** Map を Array.from() で配列にすると、[key, value]の配列になる */ 
const list = Array.from(map)
console.log('list', list);
// list (2) [Array(2), Array(2)]
// 0: ['robotama', {…}]
// 1: (2) ['piui', {…}]

MapからObjectを生成する

map.entries()の実行結果(返り値)を利用して、Object.fromEntries(map.entries())とすることで、MapからObjectを生成することができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map();

map.set("robotama", robotamaObject).set("piui", piuiObject);
console.log("map: ", map);
// map:  Map(2) {'robotama' => {…}, 'piui' => {…}}

// Map から Object の作成
const object = Object.fromEntries(map.entries());
console.log("object: ", object);
// object:  {robotama: {…}, piui: {…}}

Objectから、Mapを生成する

Object.entries(obj)の実行結果(返り値)を利用して、new Map(Object.entries(obj))とすることで、Objectから、Mapを生成することができます。

const robotamaObject = {
  name: "ロボ玉",
  like: "ひまわりの種",
  power: 1000,
  hamflag: true,
};

const piuiObject = {
  name: "ピウイ",
  like: "ミルク",
  power: 5000,
  hamflag: false,
};

const map = new Map();

map.set("robotama", robotamaObject).set("piui", piuiObject);
console.log("map: ", map);
// map:  Map(2) {'robotama' => {…}, 'piui' => {…}}

// Object から、Map の生成
const robotamaMap = new Map(Object.entries(robotamaObject));
console.log("robotamaMap: ", robotamaMap);
// robotamaMap:  Map(4) {'name' => 'ロボ玉', 'like' => 'ひまわりの種', 'power' => 1000, 'hamflag' => true}
const piuiMap = new Map(Object.entries(piuiObject));
console.log("piuiMap: ", piuiMap);
// piuiMap:  Map(4) {'name' => 'ピウイ', 'like' => 'ミルク', 'power' => 5000, 'hamflag' => false}

まとめ

JavaScriptのコレクション管理には、ObjectArrayだけでなくMapもあるので、ぜひMapを活用して見てください。

個人で、Blogもやっています、よかったら見てみてください。

https://masanyon.com/

注意事項

この記事は、AIQ 株式会社の社員による個人の見解であり、所属する組織の公式見解ではありません。

求む、冒険者!

AIQ株式会社では、一緒に働いてくれるエンジニアを絶賛、募集しております🐱🐹✨

詳しくは、Wantedly (https://www.wantedly.com/companies/aiqlab)を見てみてください。

参考・引用

https://jsprimer.net/basic/map-and-set/

https://ja.javascript.info/map-set

https://qiita.com/anqooqie/items/ab3fed5d269d278cdd2b

AIQ Tech Blog (有志)

Discussion