JavaScript 逆引き集 | localStorage 書き込み/読み出し

JavaScript JavaScript
スポンサーリンク

localStorage の基本 — localStorage.setItem('k', v) / localStorage.getItem('k')

localStorage は「ブラウザに文字列として永続保存(タブや再起動後も保持)」できる仕組みです。キーと値で扱い、値は必ず文字列になります。


まずは基礎

<script>
  // 書き込み(保存)
  localStorage.setItem("greeting", "こんにちは");

  // 読み出し(取得)
  const val = localStorage.getItem("greeting"); // "こんにちは"

  // ないキーは null
  console.log(localStorage.getItem("nope")); // null

  // 削除・全消去
  localStorage.removeItem("greeting");
  localStorage.clear();
</script>
HTML
  • 保存範囲: 同一オリジン(ドメイン・プロトコル・ポート)内で共有。
  • 型: 値は文字列。オブジェクト/配列は JSON 化が必要。

オブジェクトや配列を保存するテンプレート

// 保存(JSON化)
const user = { name: "Aki", age: 20 };
localStorage.setItem("user", JSON.stringify(user));

// 取得(JSONを復元)
const raw = localStorage.getItem("user");
const data = raw ? JSON.parse(raw) : null;
console.log(data?.name); // "Aki"
JavaScript
  • ポイント: getItemnull のときに JSON.parse(null) はエラーになるため、nullチェックを挟む。

よく使うテンプレート集

設定の保存と復元(ダークモード例)

// 保存
function saveTheme(isDark) {
  localStorage.setItem("theme", isDark ? "dark" : "light");
}

// 復元
function loadTheme() {
  const theme = localStorage.getItem("theme") || "light";
  document.documentElement.dataset.theme = theme; // data-theme="dark|light"
}
loadTheme();
JavaScript

入力内容の一時保存(フォーム復元)

const input = document.getElementById("memo");

input.addEventListener("input", () => {
  localStorage.setItem("memo:text", input.value);
});

window.addEventListener("DOMContentLoaded", () => {
  input.value = localStorage.getItem("memo:text") || "";
});
JavaScript

TODO を配列で保持(追加・削除)

const KEY = "todos";

function loadTodos() {
  const raw = localStorage.getItem(KEY);
  return raw ? JSON.parse(raw) : [];
}

function saveTodos(todos) {
  localStorage.setItem(KEY, JSON.stringify(todos));
}

function addTodo(text) {
  const todos = loadTodos();
  todos.push({ id: crypto.randomUUID(), text });
  saveTodos(todos);
}
JavaScript

実務でのコツ

  • 名前空間で整理: 関連キーに接頭辞を付ける(例: app:theme, app:user)と衝突や混乱を防げる。
  • try/catch で安全に: JSON の破損や保存容量超過に備えて、復元時は try/catch
function safeParse(raw, fallback = null) {
  try { return raw ? JSON.parse(raw) : fallback; }
  catch { return fallback; }
}
JavaScript
  • 容量の目安: 数MB程度。大量データは不向き。必要ならサーバーや IndexedDB を検討。
  • 同期 API: setItem/getItem は同期で即時に動く。高頻度で大きなデータを書き込まない。
  • storage イベント: 他タブでの変更を受け取れる。
window.addEventListener("storage", (e) => {
  if (e.key === "theme") console.log("テーマが他タブで更新:", e.newValue);
});
JavaScript
  • セキュリティ: 機密情報(トークン、個人情報)は保存しない。XSS があると読み取られる可能性があるため危険。

ありがちなハマりポイントと対策

  • nullをそのままパースしてエラー:
    • 対策: const raw = getItem(...); raw ? JSON.parse(raw) : ... の形にする。
  • 文字列として保存される誤解:
    • 対策: 数値も "123" になる。必要なら取得後に Number(...) 等で変換。
  • 容量超過(QuotaExceededError):
    • 対策: データを小さく保つ。不要キーの削除、画像や巨大テキストは保存しない。
  • 別環境で値が見つからない:
    • 対策: オリジンが違うと共有されない。サブドメインやプロトコル差異に注意。

練習問題(設定保存のミニアプリ)

<label><input type="checkbox" id="dark"> ダークモード</label>
<select id="lang">
  <option value="ja">日本語</option>
  <option value="en">English</option>
</select>

<script>
  const DARK_KEY = "app:dark";
  const LANG_KEY = "app:lang";

  // 復元
  document.getElementById("dark").checked =
    localStorage.getItem(DARK_KEY) === "1";
  document.getElementById("lang").value =
    localStorage.getItem(LANG_KEY) || "ja";

  // 変更を保存
  document.getElementById("dark").addEventListener("change", (e) => {
    localStorage.setItem(DARK_KEY, e.target.checked ? "1" : "0");
    document.documentElement.classList.toggle("dark", e.target.checked);
  });

  document.getElementById("lang").addEventListener("change", (e) => {
    localStorage.setItem(LANG_KEY, e.target.value);
    // 言語切り替えの反映はここに
  });

  // 他タブからの変更を反映
  window.addEventListener("storage", (e) => {
    if (e.key === DARK_KEY) {
      const on = e.newValue === "1";
      document.getElementById("dark").checked = on;
      document.documentElement.classList.toggle("dark", on);
    }
    if (e.key === LANG_KEY) {
      document.getElementById("lang").value = e.newValue || "ja";
    }
  });
</script>
HTML

直感的な指針

  • 「文字列で永続保存」→ JSON で包んで取り出すときに安全復元。
  • キーは整理して、小さく・安全に。機密は保存しない。
  • 他タブと連携したいなら storage イベントで即時反映。
タイトルとURLをコピーしました