Please note, this is a STATIC archive of website developer.mozilla.org from November 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

概要

DOM Storage とは、Web Applications 1.0 仕様で導入されたストレージに関する一連の機能に付けられた名称です。現在は W3C Web Storage 仕様として独立しています。DOM Storage は Cookie の代わりとなるもので、より大容量で、より安全かつ簡単に情報を保存できるように設計されています。Firefox 2Safari 4で導入されました。

注: DOM Storage は mozStorage (Mozilla の SQLite 用 XPCOM インタフェース) や セッションストア API (拡張機能用の XPCOM ストレージユーティリティ) とは別のものです。

解説

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.removeKeysessionStorage.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();
};
注: 通常のJavaScriptのプロパティアクセスメソッド経由で値を読み書きできますが、getItem および setItem メソッドの使用が推奨されています。
注: このページで説明しているどの Storage も、それにストアするものはすべてその .toString メソッドによって文字列に変換されてからストアされるということを念頭に置いてください。ですから、普通のオブジェクトをストアしようとすれば、そのオブジェクトやJSON表現がストアされるのではなく、"[object Object]"という文字列となります。オブジェクトを文字列形式にするには、ブラウザが提供するJSONのパース、文字列化のネイティブなメソッドを使うのが、普通で有効な方法でしょう。

sessionStorage

sessionStorage はページセッションの間利用できるストレージを保持するグローバルオブジェクトです。ページセッションはブラウザが開かれている間だけ継続され、ページが更新されたり復元されても持続されます。ページを新しいタブやウィンドウで開くと、新しいセッションが開始されます。

// 現在のセッションの保存領域にデータを保存する
sessionStorage.setItem("username", "John");

// 保存されたデータにアクセスする
alert( "username = " + sessionStorage.getItem("username"));

sessionStorage オブジェクトは、誤ってブラウザを更新してしまっても一時データが失われないように、そのデータを保存および復元したい場合に最も役立ちます。

Firefox 3.5 における注記

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の生成元 (スキーム+ホスト名+非標準ポート番号) へのスコープを持つこと、および localStorageStorage のインスタンスで 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 は、複数のページセッションやブラウザセッションにまたがるような長期間にわたってデータを保存できる、複数のプライベートなストレージ領域を保持するグローバルオブジェクトです。

注: globalStorageStorage のインスタンスではなく、 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 3 における注記

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

詳細

  • 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 の最大容量がここで報告されています

関連リンク

ドキュメントのタグと貢献者

 このページの貢献者: khalid32, ethertank, woby, Potappo, Marsf, Shoot, Mgjbot
 最終更新者: khalid32,