JavaScriptでデータを扱うコレクションには、Object(オブジェクト)やArray(配列)などがあります。
これらはJavaScriptであらかじめ用意されていることから、ビルドインオブジェクトとも呼ばれており、以下のような性質を持っています。

・Object(オブジェクト):キー付けされたコレクション
・Array(配列):順番付けされたコレクション

ES6からはMapとSetが導入されたことにより、データをより柔軟に扱うことができるようになりました。

そこで今回は、MapとSetについて紹介しながら、ObjectとArrayとの違いについても解説していきます。

Map

Mapとは、キーと値のペアを格納することのできるコレクションです。
ES5までは、ObjectがMapの代わりとして使われていました。
※補足ですが、ここで取り扱うMapは、Arrayで使用されるMapメソッドとは異なります。

ObjectもMapも、キー付けされたデータの集まりですが、違いもあります。
それは、Objectの場合、キーを文字列またはシンボルの型のみでしか指定できませんでしたが、Mapの場合は、キーを任意の型で取ることができるようになった点です。

Mapの基本的な使い方

ここからは、Mapの使い方を見ていきましょう。

Mapの作成/初期化

new Map()で新しいMap(空)を作成することができます。

const map = new Map();

要素を持つMapの作成

Mapの作成時に初期値を入れることも可能です。キーと値のペアを格納します。

const map = new Map([
  [1, 'One'],
  [2, 'Two'],
  [3, 'Three']
]);

要素の追加と取り出し

Mapには、setメソッドgetメソッドが用意されています。
map.set(key, value)で値の追加、map.get(key)で値の取り出しができます。

// Mapの作成
const map = new Map();
// 要素の追加
map.set(1, 'One');
// 要素の取り出し
console.log(map.get(1)); //"One"

もし、同じキー名で複数回setメソッドを使用した場合には、最後に追加された値で上書きされます。

const map = new Map();

map.set(1, 'One');
map.set(1, 'いち');
map.set(1, '1');

console.log(map.get(1)); // "1"

また、以下を見てみると、キーは文字列に限らず、任意の型でキーを指定できることが分かります。この点が、ObjectとMapの大きな違いです。

const map = new Map();

map.set(1, 'number');
map.set('1', 'string');
map.set(false, 'boolean');

console.log(map.get(1)); // "number"
console.log(map.get('1')); // "string"
console.log(map.get(false)); // "boolean"

要素の数を取得

Map内の要素の数を得るには、sizeメソッドを使用します。
作成したばかりのMapでは、0が返ります。

const map1 = new Map();
const map2 = new Map([
  [1, 'One'],
  [2, 'Two'],
  [3, 'Three']
]);

console.log(map1.size); // 0
console.log(map2.size); // 3

要素があるか確認

Map内に要素が存在するか確認するためには、hasメソッドを使います。
map.has(key)でキーが存在する場合にはtrueを返し、そうでない場合にfalseを返します。

const map = new Map();

map.set(1, 'One');

console.log(map.has(1)); // true
console.log(map.has('1')); // false

Mapの繰り返し処理

Mapでの繰り返し処理には、forEachメソッドを使用することができます。

MapのforEachメソッドは、配列で言うインデックスの代わりにキーが渡されます。

const map = new Map([
  [1, 'One'],
  [2, 'Two'],
  [3, 'Three']
]);

map.forEach((value, key) => {
  console.log(key, value);
});
// 1, "One"
// 2, "Two"
// 3, "Three"

また、Mapで繰り返し処理を行うために以下のメソッドも使われます。
この時、for…of文と一緒に用いられます。

map.keys():Mapのキーに対するiterableオブジェクトを返す
map.values():Mapの値に対するiterableオブジェクトを返す
map.entries():すべての要素のiterableオブジェクトを配列で返す

const map = new Map([
  [1, 'One'],
  [2, 'Two'],
  [3, 'Three']
]);

// キーの反復
for (let number of map.keys()) {
  console.log(number);
}
// 1
// 2
// 3

// 値の反復
for (let number of map.values()) {
  console.log(number);
}
// "One"
// "Two"
// "Three"

// [キー, 値]の反復
for (let number of map.entries()) {
  console.log(number);
}
// [1, "One"]
// [2, "Two"]
// [3, "Three"]

Set

Setとは、キー無しの値を格納することのできるコレクションです。
ArrayとSetは似た性質を持っており、複数のリファレンス型やプリミティブ型の値を保持することができます。

Arrayとの大きな違いは、Setは重複した値を持つことができない点です。
そのため、値が重複しないことを保証したい場合や、ある値を持っているか確認したい場合に、Setが役に立ちます。

Setの基本的な使い方

Setの使い方を見ていきましょう。

Setの作成/初期化

new Set()で新しいSet(空)を作成し、作成時に初期値を入れることも可能です。

const set = new Set();
const set = new Set(['One', 'Two', 'Three']);

要素の数を取得

Set内の要素の数を得るには、Mapと同様にsizeメソッドを使用します。
作成したばかりのSetでは、0が返ります。

const set1 = new Set();
const set2 = new Set(['One', 'Two', 'Three']);

console.log(set1.size); // 0
console.log(set2.size); // 3

要素の追加と削除

Setは、要素の追加や削除ができるメソッドを持ちます。
set.add(value)で値を追加し、set.delete(value)で任意の値を削除することができます。
さらに、set.clear()では、setのすべての要素を削除します。

const set = new Set();
const person = { name: 'Emma' };

// 要素の追加
set.add('One');
set.add(1);
set.add(person);
console.log(set.size); // 3

// 要素の削除
set.delete('One');
console.log(set.size); // 2

// すべての要素を削除
set.clear();
console.log(set.size); // 0

Setは、重複した要素を持たないことが特徴でもあると説明しました。
そのため、すでに持っている値をaddメソッドで渡した場合、その値は無視されます。

const set = new Set();

set.add('One');
console.log(set.size); // 1

// 重複しているため、追加されない
set.add('One');
console.log(set.size); // 1

要素があるか確認

Set内に要素が存在するか確認するためには、hasメソッドを使います。
set.has(value)で値が存在する場合にはtrueを返し、そうでない場合にfalseを返します。

const set = new Set();

set.add('One');

console.log(set.has('One')); // true
console.log(set.has(1)); // false

Setの繰り返し処理

Setでの繰り返し処理には、以下のように、forEachメソッド、またはfor…of文を使用することができます。

const set = new Set(['One', 'Two', 'Three']);

set.forEach((num) => {
  console.log(num);
});
// "One"
// "Two"
// "Three"

for (let num of set) {
  console.log(num);
}
// "One"
// "Two"
// "Three"

SetをArrayに変換

SetとArrayの性質は良く似ていますが、同じ値を持てるか持てないかの違いがあります。
しかし、Setの機能を維持しつつ、SetをArrayに変換することが可能です。
spreadオペレーターと組み合わせることで、重複をなくしたArrayをかんたんに作成することができます。

const array = [1, 2, 3, 1, 2, 3]; // 重複する値を持つ配列を作成
const set = new Set(array); // 配列からSetを作成
const newArray = [...set]; // Setを配列に変換

console.log(newArray); // [1, 2, 3]

まとめ

今回は、MapとSetについて解説しました。

MapやSetを採用することで、柔軟にデータ管理や繰り返し処理ができるようになります。

また、従来使われてきたObjectやArrayに加えて、MapやSetについても理解を深めておくと、意図しない挙動をより防ぎやすくなるため、参考にしてみてください。

MapとSetの関連記事

オブジェクト
オブジェクトの操作
配列
配列の操作