URL クラスの基本 — const u = new URL('/a', 'https://example.com')
URL クラスは「URL文字列を安全に生成・分解」するための標準APIです。相対パスと基準URLを組み合わせて絶対URLを作れたり、protocol/host/pathname/searchParams などの部品を簡単に扱えます。文字列連結の失敗(スラッシュの重複・抜け、エンコード漏れ)を避けられるのが大きな利点です。
まずは生成と主要プロパティ
// 相対 + 基準で絶対URLを生成
const u = new URL("/a", "https://example.com"); // https://example.com/a
console.log(u.href); // "https://example.com/a"
console.log(u.origin); // "https://example.com"
console.log(u.protocol); // "https:"
console.log(u.host); // "example.com"(ポート込み)
console.log(u.hostname); // "example.com"(ホスト名のみ)
console.log(u.port); // ""(指定がなければ空)
console.log(u.pathname); // "/a"
console.log(u.search); // ""(クエリがなければ空)
console.log(u.hash); // ""(ハッシュがなければ空)
JavaScript- 役割: URLの各部品を「安全に」読み書きできる。
- 相対→絶対:
new URL(relative, base)で確実に結合され、..や.の解決も自動。
よく使うテンプレート集
安全にパスを付け足す(スラッシュ問題を自動で解決)
const base = new URL("https://example.com/api/"); // 末尾スラッシュがあってもOK
const url = new URL("v1/users", base); // → https://example.com/api/v1/users
JavaScriptクエリ操作は searchParams に任せる
const url = new URL("/search", "https://example.com");
// 追加・更新・複数値
url.searchParams.set("q", "apple"); // q=apple
url.searchParams.set("page", "2"); // page=2
url.searchParams.append("tag", "red"); // tag=red&...
url.searchParams.append("tag", "fresh"); // tag=fresh
console.log(url.toString());
// https://example.com/search?q=apple&page=2&tag=red&tag=fresh
JavaScript- ラベル:
setは上書き、appendは同キー追加。エンコードは自動。
部品を書き換えてリンクを生成
const url = new URL("https://example.com/shop?page=1#top");
url.pathname = "/shop/items"; // パス変更
url.searchParams.set("page", "2"); // クエリ更新
url.hash = ""; // ハッシュ削除
console.log(url.href); // https://example.com/shop/items?page=2
JavaScript相対リンクを現在ページから解決
// ブラウザ環境なら現在ページを基準に
const img = new URL("images/photo.png", location.href);
console.log(img.href); // 現在ページのディレクトリからの絶対URL
JavaScriptユーザー入力から安全にURLを組み立てる(try/catch)
function buildUrlSafe(pathSegment, base = "https://example.com") {
try {
// パスの1セグメントに特殊文字がある場合はエンコード(searchParamsとは別)
const encoded = encodeURIComponent(pathSegment);
return new URL(`/files/${encoded}`, base).href;
} catch (e) {
return null; // 不正なURLなら安全に失敗させる
}
}
JavaScript例題:API エンドポイント生成+フェッチ
function apiUrl(path, params = {}) {
const url = new URL(path, "https://api.example.com/");
for (const [k, v] of Object.entries(params)) {
url.searchParams.set(k, String(v));
}
return url;
}
// 使い方
const url = apiUrl("v1/items", { page: 2, q: "banana" });
// https://api.example.com/v1/items?page=2&q=banana
const res = await fetch(url);
const data = await res.json();
JavaScript- ラベル: 文字列連結せずに URL クラスへ委ねると、スラッシュやエンコードの不安がなくなる。
例題:URL を分解して表示(解析ビュー)
function parseUrl(s) {
try {
const u = new URL(s);
return {
href: u.href,
origin: u.origin,
protocol: u.protocol,
host: u.host,
pathname: u.pathname,
query: Object.fromEntries(u.searchParams.entries()),
hash: u.hash,
};
} catch {
return null;
}
}
// 使い方
console.log(parseUrl("https://example.com/a/b?x=1&y=2#sec"));
// { href, origin, protocol, host, pathname: "/a/b", query: {x:"1", y:"2"}, hash:"#sec" }
JavaScript- ラベル:
searchParams.entries()でクエリを簡単にオブジェクト化。
実務でのコツ
- 文字列連結を避ける:
new URL(relative, base)で結合すれば、スラッシュ有無や..解決も自動。 - クエリは searchParams: 自前エンコード不要。複数値は
append、取得はgetAll。 - パスセグメントのエンコード: クエリ以外の「パスの一部」は
encodeURIComponentで安全に。 - 絶対 vs 相対の基準: ブラウザなら
location.hrefを、サーバーサイドでもnew URL(base, 'https://...')で明示基準を使う。 - 検証と例外: 不正な文字列には
new URL(...)が例外を出す。try/catchで処理を分けると安全。 - HTTPS強制の例: プロトコルが
http:の場合はurl.protocol = 'https:'で統一(リダイレクトやリンク生成に有効)。
ありがちなハマりポイントと対策
- 基準URLなしで相対を渡す → 例外:
- 対策: 相対は必ず
new URL(relative, base)の形にする。
- 対策: 相対は必ず
- パス結合のスラッシュ重複・欠落:
- 対策:
new URL("child", new URL("https://x/y/"))のようにクラスで結合。
- 対策:
- パスの特殊文字で崩れる:
- 対策: パスの「1セグメント」は
encodeURIComponent。クエリはsearchParamsに任せる。
- 対策: パスの「1セグメント」は
- クエリの同キー上書きミス:
- 対策: 同キー複数は
append、単値はset。読み取りはgetAll。
- 対策: 同キー複数は
練習問題(リンク生成ヘルパー)
// 1) 商品ページURLを生成: /products/:id?ref=...
function productUrl(id, ref) {
const u = new URL(`/products/${encodeURIComponent(id)}`, location.origin);
if (ref) u.searchParams.set("ref", ref);
return u.href;
}
// 2) 現在URLからページ番号を取得(デフォルト1)
function currentPage() {
const p = new URLSearchParams(location.search);
return Number(p.get("page") || 1);
}
// 3) ページ番号を差し替えたURLを履歴追加
function goToPage(n) {
const url = new URL(location.href);
url.searchParams.set("page", String(n));
history.pushState(null, "", url.toString());
}
JavaScript- ヒント:
productUrlでencodeURIComponentを使う理由は、IDにスラッシュやスペースが含まれていても安全に1セグメントとして扱うため。
