クエリ文字列を連想配列に変換する簡単なやり方 (URLSearchParams)

location.search で取得した ?hoge=fuga&foo=bar みたいなクエリ文字列をパースする時に、コレまでは npm の query-string パッケージを使ったりしていた。

もしくは、次のように自分でパースしてみたこともあった。

// slice(1) で先頭の '?' を除去している
const params = window.location.search.slice(1).split('&').reduce((acc, current) => {
  const pair  = current.split('=');
  const key   = pair[0];
  const value = pair[1];  // 場合によっては decodeURIComponent() をかませる
  acc[key] = value;
  return acc;
}, {});

今でもこの手法は有効ではあるが、最近は URLSearchParams というインターフェースがあるようだ。

const urlSearchParams = new URLSearchParams(location.search);

でインスタンス化すると色々なことが出来るようだ。先頭の ? の有無とかも気にしなくて良い。

// location.search 風な文字列を自分で作って渡してやってもちゃんと処理する
const myLocationSearch = '?hoge=fuga&foo=bar';

const pairs = [...new URLSearchParams(myLocationSearch).entries()];
// → [ [ 'hoge', 'fuga' ], [ 'foo', 'bar' ] ]

こんな風に配列にセットしてやると、Key Value のペアの配列になる。この .entries() は省略しても等価なので、クエリ文字列を連想配列にするワンライナーが以下のように作れる。

const params = [...new URLSearchParams(location.search)].reduce((acc, pair) => ({...acc, [pair[0]]: pair[1]}), {});
// → { hoge: 'fuga', foo: 'bar' }

トリッキーに見えるが、URLSearchParams に渡す引数は undefinednull・空文字・オブジェクトなど、結構メチャクチャなデータを投げつけてもうまく処理してくれる。ざっと触ってみた感じ例外が発生することはなさそうだ。

ワンライナーが厳しければ、

const pairs = [...new URLSearchParams(myLocationSearch)];

pairs.forEach((pair) => {
  const key   = pair[0];
  const value = pair[1];
});

この Key・Value ペアを作るイディオムだけでも覚えておくと、find したりなんだりがやりやすくなると思う。