TL;DR (忙しい人のための3行まとめ)
-
ブラウザにデータを永続化 できる
Key-Value型のストレージ(容量は一般的に5MB程度)。 - 保存できるのは 文字列のみ なので、オブジェクトを扱う際は
JSON.stringify/JSON.parseが必須。 - 同期処理 であるため、大量データの読み書きはメインスレッドをブロックする点に注意が必要。
Introduction
「ユーザーが選んだダークモード設定を、リロード後も保持したい」
「入力途中のフォーム内容を、誤ってタブを閉じた時のために一時保存したい」
フロントエンド開発をしていると、こういった 「サーバーに送るほどではないが、ブラウザにちょっとしたデータを残したい」 というシーンに頻繁に遭遇しますよね?
そんな時に真っ先に候補に上がるのが、Web Storage API の一つである localStorage です。 Cookie よりも扱いやすく、容量も大きいこの機能を「なんとなく」使っていませんか?
本記事では、localStorage の基本操作はもちろん、実務でハマりやすい「オブジェクトの保存」や「セキュリティの懸念点」まで、コードベースで解説します。これを読めば、適切なシーンで迷いなく localStorage を選定できるようになるでしょう。
Prerequisites (前提環境)
本記事のコードは以下の環境を想定しています。
- モダンブラウザ (
Chrome,Firefox,Edge,Safari) の最新版 -
ES6+(const/let, アロー関数等 ) が動作するJavaScript環境
1. localStorage とは? (基本概念)
localStorage は、ブラウザ内にデータを保存する Web Storage API の一種です。
主な特徴は以下の通りです。
- 永続性: ブラウザを閉じたり、PC を再起動してもデータは消えません(明示的に消すまで残る)。
-
スコープ: オリジン ( Protocol + Domain + Port ) 単位で管理されます。
http://example.comとhttps://example.comは別物として扱われます。 -
容量: ブラウザによりますが、一般的に 5MB 程度まで保存可能です(
Cookieは4KB程度)。 - データ形式: キー ( Key ) と 値 ( Value ) のペアで保存します。どちらも 文字列 ( String ) である必要があります。
sessionStorage との違い
よく比較される sessionStorage との最大の違いは 「データの寿命」 です。
| 機能 | データの寿命 | 共有範囲 | 用途 |
|---|---|---|---|
| localStorage | 半永久的 (手動削除まで) | 同一オリジンの全タブ・ウィンドウ | 設定、カート情報、キャッシュ |
| sessionStorage | タブを閉じるまで | タブ内のみ | 一時的な入力状態、画面遷移データ |
2. 基本的な操作方法 (CRUD)
API は非常にシンプルです。 window.localStorage オブジェクト(または単に localStorage )を通して操作します。
データの保存 ( setItem )
// キー 'theme', 値 'dark' を保存
localStorage.setItem('theme', 'dark');
// 💡 注意: 数値を渡しても文字列に変換されます
localStorage.setItem('visitCount', 10);
// 保存されるのは "10"
データの取得 ( getItem )
存在しないキーを指定した場合は null が返ります。
const currentTheme = localStorage.getItem('theme');
console.log(currentTheme); // "dark"
const userToken = localStorage.getItem('unknownKey');
console.log(userToken); // null
データの削除 ( removeItem / clear )
// 特定のキーを削除
localStorage.removeItem('theme');
// すべてのデータを削除(取り扱い注意!)
localStorage.clear();
3. 【重要】オブジェクトや配列を扱う方法
ここが初心者が最もハマるポイントです。 localStorage は文字列しか保存できないため、オブジェクトをそのまま保存しようとすると悲劇が起きます。
❌ 失敗例
const user = { id: 1, name: 'Taro' };
localStorage.setItem('user', user);
console.log(localStorage.getItem('user'));
// 出力: "[object Object]"
// 😱 元のデータが消失し、単なる文字列になってしまう!
⭕️ 成功例: JSON 変換を使う
オブジェクトを保存する際は、シリアライズ ( Serialization ) と デシリアライズ ( Deserialization ) を行います。
- 保存時:
JSON.stringify()で文字列化 - 取得時:
JSON.parse()でオブジェクトに戻す
const user = { id: 1, name: 'Taro' };
// 1. 保存: オブジェクト -> JSON文字列
localStorage.setItem('user', JSON.stringify(user));
// 2. 取得: JSON文字列 -> オブジェクト
const savedData = localStorage.getItem('user');
if (savedData) {
const parsedUser = JSON.parse(savedData);
console.log(parsedUser.name); // "Taro"
}
4. 実務で使える Wrapper 関数の作成
実務では、毎回 JSON.parse を書くのは冗長ですし、エラーハンドリングも必要です(容量オーバー時などに例外が発生します)。
以下のような簡易的なラッパー関数を作っておくと便利です。
const StorageUtils = {
// データを保存(try-catch で容量エラーをハンドリング)
set: (key, value) => {
try {
const jsonValue = JSON.stringify(value);
localStorage.setItem(key, jsonValue);
} catch (e) {
console.error('Storage quota exceeded or saving failed:', e);
}
},
// データを取得(パースエラーをハンドリング)
get: (key, defaultValue = null) => {
try {
const value = localStorage.getItem(key);
return value ? JSON.parse(value) : defaultValue;
} catch (e) {
console.error('Error parsing storage data:', e);
return defaultValue;
}
},
remove: (key) => {
localStorage.removeItem(key);
}
};
// 【使用例】
StorageUtils.set('settings', { volume: 50, muted: false });
const settings = StorageUtils.get('settings', { volume: 0 }); // デフォルト値も指定可能
5. 注意点とベストプラクティス
便利ですが、銀の弾丸ではありません。以下の点に注意してください。
1. 機密情報を保存しない (Security)
localStorage は JavaScript から容易にアクセス可能です。これは、クロスサイトスクリプティング ( XSS ) 脆弱性がある場合、攻撃者に中身を盗まれるリスクがあることを意味します。
- NG: JWT トークン、パスワード、個人情報、API キー
- OK: UI の設定(テーマ)、閲覧履歴、一時的なフォームデータ
2. 同期処理によるブロッキング (Performance)
localStorage の読み書きは 同期 ( Synchronous ) で行われます。つまり、巨大なデータを読み書きしている間、ブラウザの描画や操作が止まる可能性があります。
数 MB クラスのデータを扱う場合は、非同期で動作する IndexedDB の利用を検討してください。
3. ストレージイベントの活用
別タブで localStorage が更新された場合、storage イベントを検知して UI を同期させることができます。
window.addEventListener('storage', (event) => {
if (event.key === 'theme') {
// 別タブでテーマが変更されたら、このタブにも適用
applyTheme(event.newValue);
}
});
Conclusion
localStorage は、以下の要件を満たす場合に最適なソリューションです。
- 永続性が必要
- データ量が少ない (数 KB 〜 数 MB)
- 機密情報ではない
- 構造が単純 (Key-Value で管理可能)
「とりあえず Cookie」ではなく、用途に合わせて localStorage や sessionStorage、そしてより高度な IndexedDB を使い分けることが、モダンな Web エンジニアへの第一歩です。まずは手元のプロジェクトで「ダークモードの実装」あたりから試してみてはいかがでしょうか?
Next Step
- Chrome DevTools の Application タブを開き、現在閲覧しているサイトがどんなデータを
Storageに保存しているか確認してみましょう。
References
⚠️ 本記事に関する注意
- 本記事は執筆時点の情報に基づき作成しています。