JavaScriptでは文字列や数字の他に、配列やオブジェクトと言った型があります。おそらく利用した経験がある方も多いでしょう。この配列とオブジェクトに対して、より便利な機能を提供するのがSetオブジェクトとMapオブジェクトです。

この記事では配列やオブジェクトとの違いを、コードで解説していきます。

Setオブジェクト

Setオブジェクトは配列(Array)に相当するものだと言えます。

const set = new Set;
const ary = [];

一番大きな違いとして、Setは同じ値が追加できないという点が挙げられます。

set.add('a');
// => Set(1) {'a'}
set.add('a');
// => Set(1) {'a'}

もちろん配列の場合は、同じ値も追加できます。

ary.push('a');
ary.push('a');
// => ['a', 'a']

このユニークな値しか追加できないという点がメリットになる場合もあるでしょう。

Setオブジェクトのメソッドは基本的に配列と同じように操作できるものが揃っています。

要素を追加する

要素を追加するのは add メソッドです。

set.add('a');
set.add('b');

要素を削除する

delete メソッドで値を指定して削除できます。

set.delete('a');

すべて削除して空にする場合には clear メソッドを使います。

set.clear();

値が存在するか確認する

has メソッドを使って値の存在を確認します。

if (set.has('a')) {
    // 値あり
} else {
    // 値なし
}

イテレーションを使ったループ処理

Setオブジェクトでは for of を使った各種イテレーションが利用できます。たとえば、以下のようなオブジェクトを定義します。

const set = new Set;
set.add('テキスト');
set.add(100);
set.add(true);

この時、setだけでイテレーションができます。keysvalues といったメソッドもありますが、同じデータが返ってきます。

for (let item of set) console.log(item)
// => テキスト
// => 100
// => true

forEach メソッドも利用できます。

set.forEach(item => console.log(item));
// => テキスト
// => 100
// => true

配列への変換

Setオブジェクトから配列にする際には Array.from を利用します。

Array.from(set);
// => ['テキスト', 100, true]

Mapオブジェクト

Mapオブジェクトはオブジェクト型に相当するものになります。

const map = new Map;
const obj = {};

初期化する際に2次元配列を渡すことで、データを含めたMapオブジェクトを作成できます。入れ子になっている配列の1つめの値がキー、2つめが値になります。

const map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

Mapの特徴としては、キーの型が自由である点が挙げられます。オブジェクト型は文字列またはシンボルしかキーに使えませんが、Mapは関数やオブジェクトなどもキーにできます。

const map = new Map;
const date = new Date;
map.set(date, 10);
map.get(date);
// => 10
function func() {}
map.set(func, 30);
map.get(func);
// => 30

データの追加と取得

データの追加は set 、取得は get メソッドを使います。キーを使って追加もできますが、正しく動作しなくなるので注意してください。

const map = new Map;
const date = new Date;
map.set(date, 10);
map.get(date);
// => 10

データの削除

データの削除は delete メソッドを使って行います。

map.delete(date);

データをすべて削除する場合は clear メソッドを使います。

map.clear();

データの数を取得

Mapオブジェクトには size プロパティが用意されており、簡単にデータの個数を取得できます。オブジェクトの場合は Object.keys を使っていたでしょう。

map.size;
// => 3

キーの存在を確認

指定したキーが存在するかどうかは has メソッドで確認できます。

if (map.has(date)) {
    // キーが存在する
} else {
    // キーが存在しない
}

イテレーションを使ったループ処理

Mapオブジェクトでは for of を使った各種イテレーションが利用できます。たとえば、以下のようなオブジェクトを定義します。

const map = new Map;
map.set('テキスト', 100);
map.set(10, 200);
map.set(true, 300);

この時、mapだけでイテレーションできます。キーと値が配列で取得できます。これは entries メソッドと同じです。

for (let [key, item] of map) console.log({key, item})
// => {key: 'テキスト', item: 100}
// => {key: 10, item: 200}
// => {key: true, item: 300}

キーを取得してイテレーションを行う場合には keys メソッドを使います。

for (let item of map.keys()) console.log(item)
// => 'テキスト'
// => 10
// => true

逆に値を使う場合には values メソッドを使います。

for (let item of map.values()) console.log(item)
// => 100
// => 200
// => 300

forEach メソッドも利用できます。

map.forEach((item, key) => console.log({key, item}));
// => {key: 'テキスト', item: 100}
// => {key: 10, item: 200}
// => {key: true, item: 300}

まとめ

SetオブジェクトやMapオブジェクトは配列やオブジェクトで代替が効くケースも多いので、あまり利用されていないかも知れません。しかしfor文よりもforEachなどが使われることが増えている現在、使い方を覚えておくと便利に使える場面も多いでしょう。

ぜひ使いこなしてください。