概要
DOM Storage とは、Web Applications 1.0 仕様で導入されたストレージに関する一連の機能に付けられた名称です。現在は W3C Web Storage 仕様として独立しています。DOM Storage は Cookie の代わりとなるもので、より大容量で、より安全かつ簡単に情報を保存できるように設計されています。Firefox 2とSafari 4で導入されました。
解説
DOM Storage の仕組みを利用すると、文字列のキーと値のペアを安全に保存し、後で取り出して使用することが可能になります。この機能は、長期間オフラインのまま作業ができるような高度な機能を持った対話式のアプリケーションを構築するための包括的な方法を提供することを目標として追加されたものです。
Mozilla ベースのブラウザ、Internet Explorer 8以降、Safari 4以降、およびChromeはすべて、動作可能な DOM Storage 仕様を実装しています。(IEの古いバージョンにも対応して、このような機能をブラウザに依存せず使用する必要がある場合、Internet ExplorerにはDOM Storageより以前からある“userData behavior”という類似のレガシーな機能があることを知っているとよいでしょう。)
ブラウザのみを使って充分な量のデータを任意の期間永続化させる良い方法は存在しないため、DOM Storage は役立つでしょう。ブラウザの Cookie には容量に制限があり、永続化されたデータを管理する方法がサポートされていませんし、Flash Local Storage などの他の方法は外部プラグインを必要とします。
新しい DOM Storage の機能 (と Internet Explorer の userData Behavior) を使った最初の公開アプリケーションのひとつとして、Aaron Boodman 氏が作成した、メモを取るためのアプリケーション halfnote があります。このアプリケーションはメモをローカルの保存領域と (インターネットに接続できれば) サーバーに同時に保存します。 この方法によって、インターネットに常時接続できない環境でも、ユーザはバックアップを取りながら安全にメモを書くことができます。
halfnote が提示したコンセプトと実装は比較的シンプルなものでしたが、これが作成されることによって、オンラインとオフラインの両方で使用可能な新しい種類の Web アプリケーションの可能性が示されました。
リファレンス
以下に挙げるのは、すべての window
オブジェクトのプロパティとして存在するグローバルオブジェクトです。つまり、sessionStorage
または window.sessionStorage
のようにしてアクセスできます。 (これは重要なポイントです。なぜならこれにより、iframe を使って、そのデータがページに直接含まれているかどうかに関わらず、追加のデータを保存したりアクセスすることができるからです。)
Storage
これは、すべてのStorageインスタンス(sessionStorage
, globalStorage[location.hostname])
に対するコンストラクタ (Storage
) です。 Storage.prototype.removeKey = function(key){ this.removeItem(this.key(key)) }
と設定すれば、localStorage.removeKey
と sessionStorage.removeKey
にも影響します。
ただし、globalStorage
の要素は Storage
のインスタンスではなく、 StorageObsolete
のインスタンスです。
Storage
は WhatWG Storage Interface によって以下のように定義されています。
interface Storage { readonly attribute unsigned long length; [IndexGetter] DOMString key(in unsigned long index); [NameGetter] DOMString getItem(in DOMString key); [NameSetter] void setItem(in DOMString key, in DOMString data); [NameDeleter] void removeItem(in DOMString key); void clear(); };
getItem
および setItem
メソッドの使用が推奨されています。.toString
メソッドによって文字列に変換されてからストアされるということを念頭に置いてください。ですから、普通のオブジェクトをストアしようとすれば、そのオブジェクトやJSON表現がストアされるのではなく、"[object Object]"
という文字列となります。オブジェクトを文字列形式にするには、ブラウザが提供するJSONのパース、文字列化のネイティブなメソッドを使うのが、普通で有効な方法でしょう。sessionStorage
sessionStorage
はページセッションの間利用できるストレージを保持するグローバルオブジェクトです。ページセッションはブラウザが開かれている間だけ継続され、ページが更新されたり復元されても持続されます。ページを新しいタブやウィンドウで開くと、新しいセッションが開始されます。
// 現在のセッションの保存領域にデータを保存する sessionStorage.setItem("username", "John"); // 保存されたデータにアクセスする alert( "username = " + sessionStorage.getItem("username"));
sessionStorage
オブジェクトは、誤ってブラウザを更新してしまっても一時データが失われないように、そのデータを保存および復元したい場合に最も役立ちます。
Firefox 3.5 より前のバージョンでは、ブラウザがクラッシュして復元した後では、sessionStorage のデータが自動的に復元されません。Firefox 3.5 から仕様どおりに動作します。
使用例:
テキスト入力欄の内容を自動で保存します。もし誤ってブラウザを更新してしまっても、テキスト入力欄の内容が復元されるため、書いた内容が失われません。
// 値を記録するテキスト入力欄を取得 var field = document.getElementById("field"); // 自動保存された値が存在するか確認 // (ページが誤って更新された場合にのみ実行される) if ( sessionStorage.getItem("autosave")) { // テキスト入力欄の内容を復元 field.value = sessionStorage.getItem("autosave"); } // テキスト入力欄の内容を 1 秒ごとにチェック setInterval(function(){ // 取得結果を sessionStorage オブジェクトに保存 sessionStorage.setItem("autosave", field.value); }, 1000);
詳細:
localStorage
localStorage
は、同じ同一生成元(same-origin)ルールが適用される sessionStorage
と同じですが、永続します。localStorage
は Firefox 3.5 で導入されました。
localStorage
データがストアされます。このデータベースは空で、プライベートブラウジングモードが終了すると破棄されます。互換性
Storage
オブジェクトは最近標準に加えられたので、すべてのブラウザには存在しない可能性があります。以下の2つのコードのうちの1つをスクリプトの最初に挿入すれば、ネイティブでは localStorage
をサポートしていない実装でも localStorage
オブジェクトを使えます。
このアルゴリズムは、クッキーを活用して localStorage
オブジェクトを正確に模倣しています。
if (!window.localStorage) { Object.defineProperty(window, "localStorage", new (function () { var aKeys = [], oStorage = {}; Object.defineProperty(oStorage, "getItem", { value: function (sKey) { return sKey ? this[sKey] : null; }, writable: false, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "key", { value: function (nKeyId) { return aKeys[nKeyId]; }, writable: false, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "setItem", { value: function (sKey, sValue) { if(!sKey) { return; } document.cookie = escape(sKey) + "=" + escape(sValue) + "; path=/"; }, writable: false, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "length", { get: function () { return aKeys.length; }, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "removeItem", { value: function (sKey) { if(!sKey) { return; } var sExpDate = new Date(); sExpDate.setDate(sExpDate.getDate() - 1); document.cookie = escape(sKey) + "=; expires=" + sExpDate.toGMTString() + "; path=/"; }, writable: false, configurable: false, enumerable: false }); this.get = function () { var iThisIndx; for (var sKey in oStorage) { iThisIndx = aKeys.indexOf(sKey); if (iThisIndx === -1) { oStorage.setItem(sKey, oStorage[sKey]); } else { aKeys.splice(iThisIndx, 1); } delete oStorage[sKey]; } for (aKeys; aKeys.length > 0; aKeys.splice(0, 1)) { oStorage.removeItem(aKeys[0]); } for (var iCouple, iKey, iCouplId = 0, aCouples = document.cookie.split(/\s*;\s*/); iCouplId < aCouples.length; iCouplId++) { iCouple = aCouples[iCouplId].split(/\s*=\s*/); if (iCouple.length > 1) { oStorage[iKey = unescape(iCouple[0])] = unescape(iCouple[1]); aKeys.push(iKey); } } return oStorage; }; this.configurable = false; this.enumerable = true; })()); }
localStorage.setItem()
関数と localStorage.removeItem()
関数を使ってください。キーの設定や削除に localStorage.yourKey = yourValue;
や delete localStorage.yourKey;
とすることは、このコードでは保証されません。それから、名前を変えて localStorage
オブジェクトとは関係なくドキュメントのクッキーを操作するためだけに使うこともできます。これは、別の、正確さに少し欠けますが、 localStorage
オブジェクトの模倣です。上のものよりシンプルで、Internet Explorerの8未満のような古いブラウザにも対応してます。これもクッキーを活用しています。
if (!window.localStorage) { window.localStorage = { getItem: function (sKey) { if (!sKey || !this.hasOwnProperty(sKey)) { return null; } return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1")); }, key: function (nKeyId) { return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]); }, setItem: function (sKey, sValue) { if(!sKey) { return; } document.cookie = escape(sKey) + "=" + escape(sValue) + "; path=/"; this.length = document.cookie.match(/\=/g).length; }, length: 0, removeItem: function (sKey) { if (!sKey || !this.hasOwnProperty(sKey)) { return; } var sExpDate = new Date(); sExpDate.setDate(sExpDate.getDate() - 1); document.cookie = escape(sKey) + "=; expires=" + sExpDate.toGMTString() + "; path=/"; this.length--; }, hasOwnProperty: function (sKey) { return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie); } }; window.localStorage.length = (document.cookie.match(/\=/g) || window.localStorage).length; }
localStorage.getItem()
関数、 localStorage.setItem()
関数、 localStorage.removeItem()
関数を使ってください。キーの設定や削除に localStorage.yourKey
とすることは、このコードでは許されません。それから、名前を変えて localStorage
オブジェクトとは関係なくドキュメントのクッキーを操作するためだけに使うこともできます。互換性および globalStorage との関係
localStorage
は、 globalStorage[location.hostname]
とも同じですが、以下の点で異なります。HTML5の生成元 (スキーム+ホスト名+非標準ポート番号) へのスコープを持つこと、および localStorage
が Storage
のインスタンスで globalStorage[location.hostname]
が(下で説明するように) StorageObsolete
のインスタンスであることです。例えば、https://example.com は、https://example.com と同一の localStorage
オブジェクトにはアクセスできませんが、どちらも同一の globalStorage
にアクセスできます。localStorage
は標準のインタフェースですが、 globalStorage
は非標準のインタフェースなので、これらに頼るべきではありません。
次のことに注意してください。 globalStorage[location.hostname]
のプロパティを設定しても localStorage
には設定されませんし、 Storage.prototype
を拡張しても globalStorage
には影響せず StorageObsolete.prototype
の拡張のみ影響します。
globalStorage
非標準
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.
globalStorage
は、複数のページセッションやブラウザセッションにまたがるような長期間にわたってデータを保存できる、複数のプライベートなストレージ領域を保持するグローバルオブジェクトです。
globalStorage
は Storage
のインスタンスではなく、 StorageObsolete
のインスタンスを持つ StorageList
のインスタンスです。// ドメイン mozilla.org にあるスクリプトのみがアクセスできるデータを保存する globalStorage['mozilla.org'].setItem("snippet", "<b>Hello</b>, how are you?");
具体的には、globalStorage
オブジェクトを使うと、データの保存が可能なたくさんの異なるストレージオブジェクトへのアクセスが可能になります。たとえば、globalStorage
を使用した Web ページをドメイン developer.mozilla.org に作成したとすると、以下のストレージオブジェクトが利用できます。
globalStorage['developer.mozilla.org']
- サブドメイン developer.mozilla.org にあるすべての Web ページがこのストレージオブジェクトに読み書きできる。
Firefox 2 では、現在のドキュメントよりも上位のドメイン階層のストレージオブジェクトへのアクセスが許可されていましたが、Firefox 3 ではセキュリティ上の理由により許可されなくなりました。さらに、HTML 5 仕様への globalStorage
の追加案は削除され、代わりに localStorage
が追加されました。こちらは Firefox 3.5 で実装されました。
使用例:
以下の例を使用する場合には、実行結果を見たいページすべてにこれらのコードが書かれたスクリプトを挿入する必要があります。
ユーザが訪れた特定のサブドメインでユーザ名を記憶させます。
globalStorage['developer.mozilla.org'].setItem("username", "John");
ユーザがあなたのドメインにあるすべてのページを何回訪れたか記録します。
// データはすべて文字列として保存されるので parseInt が必要 globalStorage['mozilla.org'].setItem("visits", parseInt(globalStorage['mozilla.org'].getItem("visits") || 0 ) + 1);
Storage の場所とデータの消去
Firefoxでは、DOM storage のデータはプロファイルフォルダ内の webappsstore.sqlite ファイル にストアされます。(chromeappsstore.sqlite ファイルというものもありますが、特別にスタートページ(about:home)のデータや、“about:”で始まるURLのほかの内部ページのデータといった、ブラウザ自身のデータがストアされます。)
- DOM Storage を消去するには、“ツール -> 最近の履歴を消去 -> Cookies” から 消去する履歴の期間を “すべての履歴” とすることで(nsICookieManager::removeAll を通じて)できます。
- ところが、別の期間を選ぶと消去できません (bug 527667)
- ツール -> オプション -> プライバシー -> cookiesを個別に削除 には表示されません (bug 506692)
- ツール -> オプション -> 詳細 -> ネットワーク -> オフラインデータ -> 今すぐ消去 としても DOM Storage は消去されません
- そのサイトがオフラインキャッシュも使用しているのでなければ、“ツール -> オプション -> 詳細 -> ネットワーク -> オフラインデータ” のリストには表示されません。もしそのサイトがリストの中にあるならば、そのサイトの DOM Storage データは、削除ボタンを押すことでオフラインキャッシュとともに削除されます。
参照: clearing offline resources cache
詳細
- Web Storage (W3C Web Apps Working Group)
- Firefox や SeaMonkey で DOM Storage を有効/無効にする方法
例
- JavaScript Web Storage Tutorial: アドレス帳アプリケーションを作る ― 簡単なアドレス帳アプリケーションの作成を通じて、Web Storage APIの使い方を説明した実践的チュートリアル
- offline web applications at hacks.mozilla.org ― あるオフラインアプリのデモと、それの動作説明がある
- Noteboard ― すべてのデータをローカルに保存するメモ書きアプリ
- jData ― インターネット上のどのウェブサイトからでもアクセスできる、共有の localStorage オブジェクトインタフェース。Firefox 3 以降、Webkit 3.1.2 nightly 以降、IE8で動作する。書き込みにユーザの許可が必要な globalStorage[""] のようなもの。
- HTML 5 localStorage example ― すごく簡潔でわかりやすい localStorage の使用例。テキストの保存と読みだし、保存されたデータの一覧の表示方法。Firefox 3 以降で動作を確認。
- HTML5 Session Storage ― すごく簡潔な session storage の使用例。local storage の例もある。Firefox 3.6 以降で動作を確認。
Basic DOMStorage Examples― Firefox 3 以降では動作しない。現在のドメインより 1 つ上位のドメインレベルの globalStorage は、Firefox 3 で使えなくなった。halfnote― (Firefox 3 で表示が崩れる)DOM Storage を使用したメモアプリケーション
ブラウザの互換性
機能 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|
localStorage | 4 | 3.5 | 8 | 10.50 | 4 |
sessionStorage | 5 | 2 | 8 | 10.50 | 4 |
globalStorage | 未サポート | 2 | 未サポート | 未サポート | 未サポート |
機能 | Android | Firefox Mobile (Gecko) | IE Phone | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
基本サポート | ? | ? | ? | ? | ? |
ブラウザによって localStorage と sessionStorage の最大容量はまちまちです。いろいろなブラウザでの Storage の最大容量がここで報告されています。