自分で split() しないでください。URLSearchParams が符号化も復号も同じ値の複数指定も扱います。必ず文字列で返ること、空とキー無しの見分け、+ と %20 の違いまで実行して確かめます。
答え
split() で自分で分解しないでください。
example.js
const params = new URLSearchParams('?q=猫&page=2');
console.log(params.get('q'));
console.log(params.get('page'));
出力書き換えて実行できます
猫
2
javascript
const params = new URLSearchParams('page=2');
const page = params.get('page');
console.log(typeof page);
console.log(page + 1);
string
21
先頭の ? は付いていても付いていなくても構いません。
復号は自動です。%E7%8C%AB のままにはなりません。
これは言語ではなくブラウザ側の仕様(URL Standard)ですが、Node にも同じものが入っています。どちらでも同じように使えます。
値は必ず文字列で返る
example.js
const params = new URLSearchParams('page=2');
const page = Number(params.get('page'));
console.log(page + 1);
出力書き換えて実行できます
3
example.js
const params = new URLSearchParams('a=&b=1');
console.log(JSON.stringify(params.get('a')));
console.log(JSON.stringify(params.get('none')));
console.log(params.has('a'), params.has('none'));
出力書き換えて実行できます
""
null
true false
足し算のつもりが繋がりました。
数として使うなら、その場で変換してください。
javascript
const params = new URLSearchParams('keyword=');
console.log(JSON.stringify(params.get('keyword') || 'すべて'));
console.log(JSON.stringify(params.get('keyword') ?? 'すべて'));
"すべて"
""
example.js
const params = new URLSearchParams('tag=a&tag=b');
console.log(params.get('tag'));
console.log(params.getAll('tag'));
出力書き換えて実行できます
a
[ 'a', 'b' ]
→ 文字列を数値に変換する
無いキーは null
example.js
const params = new URLSearchParams({ q: '猫 犬', page: '2' });
console.log(params.toString());
出力書き換えて実行できます
q=%E7%8C%AB+%E7%8A%AC&page=2
example.js
const params = new URLSearchParams({ page: '2' });
params.append('tag', 'a');
params.append('tag', 'b');
console.log(params.toString());
params.set('tag', 'c');
console.log(params.toString());
params.delete('page');
console.log(params.toString());
出力書き換えて実行できます
page=2&tag=a&tag=b
page=2&tag=c
tag=c
「空で指定されている」と「そもそも無い」は別です。
get() だけでは見分けられないので、has() を使ってください。
既定値を入れるときも、この差が効きます。
example.js
const url = new URL('https://codetaizen.com/ja/search/?q=1');
url.searchParams.set('q', '猫');
url.searchParams.set('page', '2');
console.log(url.toString());
console.log(url.pathname, url.origin);
出力書き換えて実行できます
https://codetaizen.com/ja/search/?q=%E7%8C%AB&page=2
/ja/search/ https://codetaizen.com
example.js
console.log(new URLSearchParams({ a: 'x y' }).toString());
console.log(encodeURIComponent('x y'));
出力書き換えて実行できます
a=x+y
x%20y
|| は空文字も既定値に倒します。どちらが正しいかは仕様しだいです。
→ ?. と ??
同じキーが複数あるとき
example.js
console.log(new URLSearchParams('a=x+y').get('a'));
console.log(new URLSearchParams('a=x%20y').get('a'));
出力書き換えて実行できます
x y
x y
javascript
const query = 'q=%E7%8C%AB&tag=a&tag=b';
const parsed = Object.fromEntries(query.split('&').map((part) => part.split('=')));
console.log(parsed);
{ q: '%E7%8C%AB', tag: 'b' }
get() は最初の1つしか返しません。
チェックボックスのように複数付きうるものは、必ず getAll() です。
組み立てる
符号化も自動です。 encodeURIComponent() を自分で呼ぶ必要はありません。
| したいこと |
使うもの |
| 足す(同じキーを増やす) |
append() |
| 置き換える(同じキーは1つに) |
set() |
| 消す |
delete() |
set() は同じキーを全部まとめて1つにします。 増やしたいなら append() です。
URL ごと組み立てる
url.searchParams を触ると、url 自身も書き換わります。
文字列を繋いで組み立てるより、こちらのほうが安全です。
スペースが + になる
同じスペースでも書き方が2つあります。
クエリ文字列では + が歴史的に使われ、URLSearchParams はそちらを選びます。
読むときはどちらも正しく戻ります。
自分で encodeURIComponent() した文字列を、さらに set() に渡さないでください。
二重に符号化され、%2520 のような形になります。
よくある間違い:split() で自分で分ける
2つ壊れています。
- 復号されないので
%E7%8C%AB のまま
- 同じキーが後ろで上書きされて 1つ消えた
値の中に = が入っていれば、そこでも切れます。
自分で書かないでください。
まとめ
- クエリは
URLSearchParams に任せる。split() で分けない
- 返るのは必ず文字列。数として使うなら変換する
- 無いキーは
null、空指定は空文字。見分けるなら has()
- 同じキーが複数あるなら
getAll()
- 足すのは
append()、置き換えるのは set()
- 符号化は自動。自分で符号化してから渡さない
- URL ごと扱うなら
new URL() の searchParams