「クエリ削除」で本当にやりたいこと
「クエリ削除」は、URL の ? 以降に付いているパラメータのうち、いらないものだけを取り除いて、新しい URL を作り直す処理です。
例えば、こんなことをやりたい場面があります。
- 一度だけ使う
tokenパラメータを、処理後に URL から消したい pageだけリセットして、他の検索条件は残したいdebug=trueみたいな一時的なフラグを URL から取り除きたい
つまり、「URL 全体を文字列としてゴリゴリ書き換える」のではなく、
クエリを“構造として”扱って、特定のキーだけ消して再組み立てするユーティリティを作る、という話です。
全体の流れをざっくり分解する
何をどう分けて考えるか
クエリ削除は、次の 3 ステップに分解できます。
- URL を「ベース部分」と「クエリ部分」に分ける
例:/search?q=js&page=2→ ベース/search、クエリ?q=js&page=2 - クエリ部分をパースして、オブジェクトにする
例:?q=js&page=2→{ q: "js", page: "2" } - 消したいキーを取り除いて、クエリを再生成し、ベースとくっつける
この「分解 → 編集 → 再組み立て」を毎回手でやるのは面倒なので、
ユーティリティに閉じ込めてしまいます。
基本の部品:クエリのパースと生成
すでに持っていると便利な 2 つ
ここまでの流れを前提に、クエリ削除の前に「土台」となる 2 つの関数をおさらいしておきます。
クエリ文字列 → オブジェクト
function parseQueryString(qs) {
const result = {};
if (!qs) return result;
const query = qs.startsWith("?") ? qs.slice(1) : qs;
if (query === "") return result;
const pairs = query.split("&");
for (const pair of pairs) {
if (!pair) continue;
const [rawKey, rawValue = ""] = pair.split("=", 2);
const key = decodeURIComponent(rawKey);
const value = decodeURIComponent(rawValue);
result[key] = value;
}
return result;
}
JavaScriptオブジェクト → クエリ文字列
function toQueryString(params) {
if (!params || typeof params !== "object") {
return "";
}
const parts = [];
for (const [key, value] of Object.entries(params)) {
if (value == null) continue;
const encodedKey = encodeURIComponent(key);
const encodedValue = encodeURIComponent(String(value));
parts.push(`${encodedKey}=${encodedValue}`);
}
if (parts.length === 0) {
return "";
}
return "?" + parts.join("&");
}
JavaScriptこの 2 つがあれば、「クエリを構造として扱う」準備は整っています。
URL から特定のクエリを削除するユーティリティ
removeQueryParams の実装
ここからが本題です。
「URL 文字列」と「消したいキーの配列」を受け取って、新しい URL を返す関数を作ります。
function removeQueryParams(url, keysToRemove) {
if (!url) return "";
const str = String(url);
const [base, qsAndHash = ""] = str.split("?", 2);
let qsPart = "";
let hashPart = "";
const hashIndex = qsAndHash.indexOf("#");
if (hashIndex >= 0) {
qsPart = qsAndHash.slice(0, hashIndex);
hashPart = qsAndHash.slice(hashIndex); // "#" を含む
} else {
qsPart = qsAndHash;
}
const params = parseQueryString(qsPart);
const removeSet = new Set(keysToRemove);
for (const key of removeSet) {
delete params[key];
}
const newQs = toQueryString(params);
return base + newQs + hashPart;
}
JavaScript重要ポイントをかみ砕いて説明する
ここ、少し長いですが、1 個ずつ整理します。
1. URL を「ベース」「クエリ」「ハッシュ」に分ける
const [base, qsAndHash = ""] = str.split("?", 2);
JavaScript"?" で 2 つに分けて、
base→/searchなどqsAndHash→q=js&page=2#section1など
に分解しています。
さらに、# があるかどうかで分けます。
const hashIndex = qsAndHash.indexOf("#");
if (hashIndex >= 0) {
qsPart = qsAndHash.slice(0, hashIndex);
hashPart = qsAndHash.slice(hashIndex); // "#..." をそのまま保持
} else {
qsPart = qsAndHash;
}
JavaScriptこうすることで、
- クエリ部分:
q=js&page=2 - ハッシュ部分:
#section1
のように分けて扱えます。
ハッシュ(#以降)はサーバーに送られない「フロント側だけの情報」なので、
クエリ削除では触らず、そのまま戻してあげるのが自然です。
2. クエリ部分をオブジェクトにする
const params = parseQueryString(qsPart);
JavaScriptさっきの parseQueryString を使って、"q=js&page=2" → { q: "js", page: "2" }
のように変換します。
3. 削除したいキーを Set にして一気に消す
const removeSet = new Set(keysToRemove);
for (const key of removeSet) {
delete params[key];
}
JavaScriptkeysToRemove は ["page", "token"] のような配列を想定しています。
Set にしておくと、重複があっても 1 回だけ処理されるし、
「削除対象の一覧」としても扱いやすいです。
delete params[key] で、そのキーをオブジェクトから取り除きます。
4. 残ったパラメータでクエリを再生成する
const newQs = toQueryString(params);
return base + newQs + hashPart;
JavaScripttoQueryString が、残ったパラメータから "?q=js" のような文字列を作ってくれます。
クエリが空になった場合は "" を返すようにしてあるので、base + "" + hashPart となり、? が残らないのもポイントです。
実際の使用例でイメージを固める
一度だけ使う token を削除する
const url = "https://example.com/reset-password?token=abc123&from=email";
const cleaned = removeQueryParams(url, ["token"]);
// "https://example.com/reset-password?from=email"
JavaScript処理が終わったあとに、この cleaned を history.replaceState などで URL に反映すれば、
「ブラウザのアドレスバーから token を消す」ことができます。
ページ番号だけリセットしたい
const url = "/search?q=JavaScript&page=3&sort=created_at";
const resetPageUrl = removeQueryParams(url, ["page"]);
// "/search?q=JavaScript&sort=created_at"
JavaScript「検索条件はそのまま、ページだけ 1 ページ目に戻したい」という UI でよく使うパターンです。
ハッシュ付き URL でもちゃんと動く
const url = "/docs?page=2#section1";
const cleaned = removeQueryParams(url, ["page"]);
// "/docs#section1"
JavaScript#section1 はそのまま残しつつ、page だけ消えているのが分かると思います。
設計として意識してほしいこと
「文字列置換」ではなく「構造として扱う」
クエリ削除で一番やりがちなのは、こういう書き方です。
url.replace("page=2", "");
JavaScriptこれは一見動きますが、
page=20の一部まで消してしまうpage=2が途中にあると&の位置が崩れる- URL エンコードされた値に
page=2が含まれていたら誤爆する
など、地味に危険です。
だからこそ、
- URL を「ベース」「クエリ」「ハッシュ」に分ける
- クエリをパースしてオブジェクトにする
- オブジェクトを編集してから再生成する
という「構造として扱う」アプローチが、業務レベルでは圧倒的に安全です。
「生成」「取得」「削除」をセットで揃える
ここまでで、
- クエリ生成:
toQueryString - クエリ取得:
parseQueryString/getQueryParam - クエリ削除:
removeQueryParams
という 3 兄弟が揃いました。
これらを 1 つのモジュール(queryUtils.ts みたいな)にまとめておくと、
URL 周りの処理がすべて「そこを見れば分かる」状態になります。
ちょっとだけ手を動かしてみる
コンソールで、次の順番で試してみてください。
removeQueryParams("/search?q=js&page=2&sort=created_at", ["page"]);
removeQueryParams("/search?q=js&page=2#top", ["page"]);
removeQueryParams("https://example.com/reset?token=abc&from=email", ["token"]);
JavaScript「どのパラメータが消えて、? や # がどう残るか」を、自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function parseQueryString(...) { ... }
export function toQueryString(...) { ... }
export function removeQueryParams(...) { ... }
JavaScriptを置いて、
- クエリを読む →
parseQueryString - クエリを作る →
toQueryString - クエリを消す →
removeQueryParams
という流れをルール化してみてください。
その瞬間、あなたの URL 周りのコードは、
場当たり的な文字列操作から、意図と安全性を両立した“業務レベルのクエリ操作ユーティリティ”に一段レベルアップします。

