JavaScript Tips | 文字列ユーティリティ:URL 系 - ハッシュ取得

JavaScript JavaScript
スポンサーリンク

「ハッシュ取得」で何を取りたいのか

ここでの「ハッシュ取得」は、URL の # 以降の部分(フラグメント)を、きれいに取り出して使いやすくするユーティリティのことです。

例えば、こんな URL を考えます。

https://example.com/docs?page=2#section-3

この #section-3 の部分を取り出して、

  • どのセクションを開くか決める
  • スクロール位置を決める
  • SPA(シングルページアプリ)の「画面状態」として使う

といったことをしたくなります。

そのときに、「毎回文字列を手で切る」のではなく、
“ハッシュだけを安全に取り出す小さな関数”を持っておくと、コードが一気に読みやすくなります。


まずは「ハッシュ」の基本を整理する

ハッシュ(フラグメント)とは何か

URL のうち、# 以降の部分を「フラグメント」または「ハッシュ」と呼びます。

https://example.com/path?query=1#ここがハッシュ

特徴はこうです。

  • # 以降はサーバーには送られない(ブラウザ側だけの情報)
  • ページ内リンク(<a href="#section1">)などでよく使われる
  • SPA では「画面状態」や「ルーティング」に使われることもある

だから、「クエリ(?以降)」とは役割が違います。
クエリはサーバーに届く条件、ハッシュはフロント側だけの状態、というイメージです。


一番シンプルな「ハッシュ取得」ユーティリティ

URL 文字列から # 以降を取り出す

まずは、「URL 文字列からハッシュ部分だけを取り出す」関数を作ります。

function getHash(url) {
  if (!url) return "";

  const str = String(url);

  const hashIndex = str.indexOf("#");
  if (hashIndex < 0) {
    return "";
  }

  return str.slice(hashIndex + 1);
}
JavaScript

ここが重要ポイントです。

  • indexOf("#")# の位置を探す
  • 見つからなければハッシュはないので空文字を返す
  • 見つかったら、その次の位置から最後までを slice で取り出す

動きのイメージを見てみましょう。

getHash("https://example.com/docs#section-3");
// "section-3"

getHash("/path?page=2#top");
// "top"

getHash("/path?page=2");
// ""(ハッシュなし)
JavaScript

このレベルでも、「ハッシュを文字列として取り出す」という目的は達成できます。


ブラウザ環境なら location.hash も使える

window.location.hash の挙動

ブラウザ上なら、window.location.hash というプロパティでもハッシュを取得できます。

// 例: URL が https://example.com/docs?page=2#section-3 のとき
window.location.hash; // "#section-3"
JavaScript

注意してほしいのは、先頭に # が付いたまま返ってくることです。

なので、よくやるのはこういう小さなラッパーです。

function getCurrentHash() {
  const h = window.location.hash || "";
  return h.startsWith("#") ? h.slice(1) : h;
}
JavaScript

これで、

// URL: https://example.com/docs#section-3
getCurrentHash(); // "section-3"
JavaScript

のように、「# を除いたハッシュ文字列」が取れるようになります。


ハッシュを「キー=値」の形で使いたい場合

#tab=profile のような使い方

SPA やタブ UI などで、ハッシュを「状態」として使うことがあります。

#tab=profile
#view=list
#modal=login

この場合、「ハッシュ全体を文字列として扱う」のではなく、
「クエリと同じように key=value としてパースしたい」ことが多いです。

ハッシュを 1 つのパラメータとしてパースする

まずは、「key=value 1 個だけ」の前提でパースする関数です。

function parseHashParam(hash) {
  if (!hash) return { key: "", value: "" };

  const str = hash.startsWith("#") ? hash.slice(1) : hash;

  if (str === "") return { key: "", value: "" };

  const [rawKey, rawValue = ""] = str.split("=", 2);

  const key = decodeURIComponent(rawKey);
  const value = decodeURIComponent(rawValue);

  return { key, value };
}
JavaScript

動きはこうなります。

parseHashParam("#tab=profile");
// { key: "tab", value: "profile" }

parseHashParam("view=list");
// { key: "view", value: "list" }

parseHashParam("#justKey");
// { key: "justKey", value: "" }
JavaScript

ここでも、クエリと同じように decodeURIComponent を使っているのがポイントです。
#tab=JavaScript%20入門 のようなハッシュも、ちゃんと元に戻せます。


ハッシュを「複数パラメータ」として扱う応用

#tab=profile&modal=login のような形

少し進んだ使い方として、ハッシュの中に複数の状態を詰め込むこともあります。

#tab=profile&modal=login

これを

{ tab: "profile", modal: "login" }
JavaScript

のように扱いたい場合は、クエリと同じようにパースできます。

function parseHashAsQuery(hash) {
  if (!hash) return {};

  const str = hash.startsWith("#") ? hash.slice(1) : hash;

  if (str === "") return {};

  const pairs = str.split("&");
  const result = {};

  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

使い方はこうです。

parseHashAsQuery("#tab=profile&modal=login");
// { tab: "profile", modal: "login" }

parseHashAsQuery("view=list");
// { view: "list" }
JavaScript

「クエリ生成・取得」と同じパターンを、ハッシュにも適用しているイメージです。


設計として意識してほしいこと

「ハッシュはフロント専用の状態」と割り切る

ハッシュはサーバーに送られないので、
「フロントエンドだけで完結する状態」を表すのに向いています。

例えば、

  • どのタブが選択されているか
  • どのセクションまでスクロールしたか
  • モーダルが開いているかどうか

などをハッシュで表現しておくと、
ページをリロードしても状態を再現できたり、URL を共有しても同じ状態を再現できたりします。

そのときに、「ハッシュ取得ユーティリティ」があると、
どのコードからも同じルールでハッシュを読めるようになります。

「クエリ」と「ハッシュ」を混同しない

よくある混乱は、

  • クエリ(?以降)に入れるべきものをハッシュに入れてしまう
  • ハッシュに入れるべきものをクエリに入れてしまう

というパターンです。

ざっくり分けると、

  • サーバー側の処理に関係する条件 → クエリ
  • フロント側だけの表示状態 → ハッシュ

という使い分けを意識しておくと、設計がきれいになります。


ちょっとだけ手を動かしてみる

ブラウザのコンソールで、次の順番で試してみてください。

getHash("https://example.com/docs?page=2#section-3");
getHash("/path#top");
getHash("/path");

getCurrentHash(); // 実際の URL によって結果が変わります

parseHashParam("#tab=profile");
parseHashAsQuery("#tab=profile&modal=login");
JavaScript

「どの部分がハッシュとして取れて、# がどう扱われるか」
key=value 形式のハッシュがどうオブジェクトになるか」

を、自分の目で確認してみてください。

そのうえで、自分のプロジェクトに

export function getHash(...) { ... }
export function getCurrentHash(...) { ... }
export function parseHashParam(...) { ... }
export function parseHashAsQuery(...) { ... }
JavaScript

のような関数を置いて、

  • URL 文字列からハッシュを取りたい → getHash
  • 現在のページのハッシュを取りたい → getCurrentHash
  • ハッシュを 1 つのパラメータとして扱いたい → parseHashParam
  • ハッシュを複数パラメータとして扱いたい → parseHashAsQuery

という使い分けをルール化してみてください。

それだけで、あなたの「ハッシュ取得」は、
場当たり的な split("#") から、意図と再利用性を両立した“業務レベルの URL ハッシュユーティリティ”に一段レベルアップします。

タイトルとURLをコピーしました