Closed13

Web Storage APIって何

Yug (やぐ)Yug (やぐ)

ほう、そういえばcookieと違ってWeb Storage APIはストレージを前提に作られてるからcookieのように毎回サーバでsessionIDからDBリクエストして情報取って...という接続時間がかかる問題はない、なぜならサーバと通信することがほぼ無いから、みたいなことを確かここで見たな

ウェブストレージ API (Web Storage API) は、Cookie を使用するよりも直観的な方法で、ブラウザーがキーと値のペアを保存できる仕組みを提供します。

でも今思ったけど、サーバと通信しないストレージって何のために存在するんや...?

Yug (やぐ)Yug (やぐ)

なるほど

ウェブストレージには、以下の 2 種類の仕組みがあります。

  • sessionStorage は、ページのセッション中(ページの再読み込みや復元を含む、ブラウザーを開いている間)に使用可能な、オリジンごとに区切られた保存領域を管理します。
    • 1 セッションのデータのみを保存します。つまり、データはブラウザー(またはタブ)が閉じられるまで保存されます。
    • データがサーバーに転送されることはありません。
    • ストレージの上限が Cookie よりも大きいです(最大 5MB)。
  • localStorage も同様ですが、こちらはブラウザーを閉じたり再び開いたりしても持続します。
    • 有効期限なしでデータを保存し、JavaScript によるクリア、もしくは、ブラウザーキャッシュ/ローカルに保存したデータのクリアによってのみクリアされます。
    • ストレージ制限は 2 つの中で最大です。
  • オリジンごとに区切られてるんだ
  • サーバとの接続は完全に無さそう
    • それでも確かに効果はあるか。セッション中はずっとログイン状態が保持されるから認証ページを見れる、とかそういう感じか
  • んでlocalStorageずっと残ってるなら、大分危険な気がするな...
Yug (やぐ)Yug (やぐ)

へぇ~~

これらの仕組みは Window.sessionStorage および Window.localStorage プロパティ(正確には、サポートするブラウザーは Window オブジェクトが WindowLocalStorage および WindowSessionStorage オブジェクトを実装しており、これらに localStorage および sessionStorage プロパティがあります)を通して使用でき、いずれかのプロパティを使用すると Storage オブジェクトのインスタンスを生成して、データアイテムの保存、取り出し、削除ができます。 同じオリジンに対して sessionStorage と localStorage は、別の Storage オブジェクトを使用します。 これらは別々に制御されて機能します。

Storageオブジェクトとやらを見てみる
https://developer.mozilla.org/ja/docs/Web/API/Storage

ん、更新できそうだな..?(mdnには読み取り専用って書いてあったのなぜだろう)
https://developer.mozilla.org/ja/docs/Web/API/Storage/setItem

とりあえずどっちも確かにStorageのインスタンスっぽいのでsetItem使えば普通に更新できそうだ

node_modules\typescript\lib\lib.dom.d.ts
declare var sessionStorage: Storage;
declare var localStorage: Storage;

interface Storage {
    /**
     * Returns the number of key/value pairs.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Storage/length)
     */
    readonly length: number;
    /**
     * Removes all key/value pairs, if there are any.
     *
     * Dispatches a storage event on Window objects holding an equivalent Storage object.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Storage/clear)
     */
    clear(): void;
    /**
     * Returns the current value associated with the given key, or null if the given key does not exist.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Storage/getItem)
     */
    getItem(key: string): string | null;
    /**
     * Returns the name of the nth key, or null if n is greater than or equal to the number of key/value pairs.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Storage/key)
     */
    key(index: number): string | null;
    /**
     * Removes the key/value pair with the given key, if a key/value pair with the given key exists.
     *
     * Dispatches a storage event on Window objects holding an equivalent Storage object.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Storage/removeItem)
     */
    removeItem(key: string): void;
    /**
     * Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
     *
     * Throws a "QuotaExceededError" DOMException exception if the new value couldn't be set. (Setting could fail if, e.g., the user has disabled storage for the site, or if the quota has been exceeded.)
     *
     * Dispatches a storage event on Window objects holding an equivalent Storage object.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Storage/setItem)
     */
    setItem(key: string, value: string): void;
    [name: string]: any;
}

declare var Storage: {
    prototype: Storage;
    new(): Storage;
};
Yug (やぐ)Yug (やぐ)

いやwindow.つまりwindowオブジェクトのプロパティとしても存在していて確かにそっちではreadonlyだった

ふーむ、どっちになるんだろう、更新可能なのか更新不可なのか

node_modules\typescript\lib\lib.dom.d.ts
interface WindowSessionStorage {
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage) */
    readonly sessionStorage: Storage;
}

interface WindowLocalStorage {
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/localStorage) */
    readonly localStorage: Storage;
}

んでwindowWindowLocalStorageWindowSessionStorageも継承してる

interface Window extends EventTarget, AnimationFrameProvider, GlobalEventHandlers, WindowEventHandlers, WindowLocalStorage, WindowOrWorkerGlobalScope, WindowSessionStorage {

ちなみにreadonlyとconstの違い

constは変数自体を代入不可するものです。変数がオブジェクトの場合、プロパティへの代入は許可されます。一方、readonlyはプロパティを代入不可にするものです。変数自体を置き換えるような代入は許可されます。

https://typescriptbook.jp/reference/values-types-variables/object/readonly-vs-const#constとreadonlyの違い

Yug (やぐ)Yug (やぐ)

あーでもそっか
WindowSessionStorage.sessionStorage = 〇〇、というかまぁwindowが継承してるので、window.sessionStorage = 〇〇という代入は当然readonlyにより不可能だけど、window.sessionStorage.setItem(...)は当然使えるのか。んでそれによってsessionStorageを更新することも可能になると。

gemini-2.0-pro-exp-02-05

ご質問ありがとうございます。sessionStoragelocalStoragereadonly に関する混乱について、詳しく解説します。

結論

  • window.sessionStoragewindow.localStoragereadonly ですが、これはプロパティの再代入ができないという意味です。
  • sessionStoragelocalStorage (グローバル変数) は readonly ではありません。これらの変数を通して、Storage オブジェクトのメソッド (setItem, removeItem など) を使用してデータの更新は可能です。

詳細解説

提示されたコードには、3つの異なる宣言があります。

  1. WindowSessionStorage / WindowLocalStorage インターフェース:

    • window オブジェクトのプロパティとしての sessionStoragelocalStorage を定義しています。
    • これらは readonly となっており、window.sessionStorage = anotherStorageObject; のように、別のオブジェクトを代入することはできません。
    • しかし、window.sessionStorage.setItem(...) のように、Storage オブジェクトのメソッドを呼び出して中身を変更することは可能です。
  2. グローバル変数 sessionStorage / localStorage:

    • window. を付けずに直接アクセスできるグローバル変数としての sessionStoragelocalStorage を定義しています。
    • これらは readonly ではないため、理論的には別のオブジェクトを代入できます (通常は行いません)。
    • sessionStorage.setItem(...) のように、Storage オブジェクトのメソッドを呼び出してデータの更新が可能です。
  3. Storage インターフェース:

    • sessionStoragelocalStorage が持つべきメソッドやプロパティ (length, setItem, getItem など) を定義しています。
    • length プロパティは readonly ですが、これはキーと値のペアの数を直接変更できないことを意味します。
    • setItem, removeItem, clear などのメソッドは readonly ではないため、これらを使ってデータの追加、削除、全消去が可能です。

readonly の意味

readonly キーワードは、文脈によって少し異なる意味を持ちます。

  • オブジェクトのプロパティの場合: プロパティへの再代入を禁止します。
  • インターフェースのプロパティの場合: そのプロパティが読み取り専用であることを示し、再代入を禁止します。
  • 変数の場合: 変数への再代入を禁止します(constに似ています)

まとめ

window.sessionStoragewindow.localStorage は、window オブジェクトのプロパティとしては readonly ですが、Storage オブジェクト自体は readonly ではなく、メソッドを通じてデータを変更できます。 グローバル変数 sessionStoragelocalStorageも同様です。Storage インターフェース内の length プロパティは readonly ですが、これはキーと値のペアの数を直接変更できないことを意味し、データの変更を妨げるものではありません。

この設計により、sessionStoragelocalStorage の参照自体は保護しつつ、データの操作は柔軟に行えるようになっています。

Yug (やぐ)Yug (やぐ)

再見

ウェブストレージには、以下の 2 種類の仕組みがあります。

  • sessionStorage は、ページのセッション中(ページの再読み込みや復元を含む、ブラウザーを開いている間)に使用可能な、オリジンごとに区切られた保存領域を管理します。
    • 1 セッションのデータのみを保存します。つまり、データはブラウザー(またはタブ)が閉じられるまで保存されます。
    • データがサーバーに転送されることはありません。
    • ストレージの上限が Cookie よりも大きいです(最大 5MB)。
  • localStorage も同様ですが、こちらはブラウザーを閉じたり再び開いたりしても持続します。
    • 有効期限なしでデータを保存し、JavaScript によるクリア、もしくは、ブラウザーキャッシュ/ローカルに保存したデータのクリアによってのみクリアされます。
    • ストレージ制限は 2 つの中で最大です。

どっちもストレージとして最初から作られてるつまりサーバとの通信は無いから、cookieよりストレージ制限(容量)が大きい

んでsessionStorageよりもlocalStorageの方が大きい。ずっと残る性質上どんどん増えていくものだからだろう

Yug (やぐ)Yug (やぐ)

windowはグローバルなのでwindow.は省略してもwindow.XXStorageとして呼び出されるはずだが、だとすると以下のグローバルに宣言してる部分は使われないので不要では?

declare var sessionStorage: Storage;
declare var localStorage: Storage;

あーでもwindowをグローバルとして使用できるのはサポートしてるブラウザだけで、それ以外ではwindowが使えなかったりするからその時のために作ってある、てことなのかな?

それか過去の名残が残っちゃってるだけとかもあり得る

Yug (やぐ)Yug (やぐ)

StorageEvent

storage イベントは、保存領域が変更されたときにドキュメントの Window オブジェクトで発生します。

StorageEventインタフェース

StorageEvent インターフェイスは storage イベントによって実装され、ウィンドウがアクセスするストレージ領域が他の文書のコンテキスト内で変更されたときにウィンドウに送られます。

https://developer.mozilla.org/ja/docs/Web/API/StorageEvent

これか

lib.dom.d.ts
/**
 * A StorageEvent is sent to a window when a storage area it has access to is changed within the context of another document.
 *
 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/StorageEvent)
 */
interface StorageEvent extends Event {
    /**
     * Returns the key of the storage item being changed.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/StorageEvent/key)
     */
    readonly key: string | null;
    /**
     * Returns the new value of the key of the storage item whose value is being changed.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/StorageEvent/newValue)
     */
    readonly newValue: string | null;
    /**
     * Returns the old value of the key of the storage item whose value is being changed.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/StorageEvent/oldValue)
     */
    readonly oldValue: string | null;
    /**
     * Returns the Storage object that was affected.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/StorageEvent/storageArea)
     */
    readonly storageArea: Storage | null;
    /**
     * Returns the URL of the document whose storage item changed.
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/StorageEvent/url)
     */
    readonly url: string;
    /**
     * @deprecated
     *
     * [MDN Reference](https://developer.mozilla.org/docs/Web/API/StorageEvent/initStorageEvent)
     */
    initStorageEvent(type: string, bubbles?: boolean, cancelable?: boolean, key?: string | null, oldValue?: string | null, newValue?: string | null, url?: string | URL, storageArea?: Storage | null): void;
}
Yug (やぐ)Yug (やぐ)

なるほど、やはりイベントだからユーザからのイベントに動的に反応できてる

また、event output ページも提供します。 このページを別のタブで開くと、ランディングページで選択肢を変更したときに StorageEvent が発生するのに応じて、更新されたストレージの情報が出力されるのを確認できます。

Yug (やぐ)Yug (やぐ)

へぇ~なるほど

プライベートウィンドウ、シークレットモード、および同様の名前のプライバシーブラウジングオプションでは、履歴やクッキーのようなデータは格納されません。プライベートモードでは localStorage は sessionStorage のように扱われます。ストレージ API が利用可能で完全に機能しますが、プライベートウィンドウに格納されたデータはすべてブラウザーまたはブラウザータブが閉じられたときに削除されます。

  • 履歴/cookieはプライベートウィンドウで保存されない
  • プライベートウィンドウではlocalStorageがsessionStorageみたいになるから、実質2つとも同じようになる
    • だからタブ(ブラウザー)閉じたらストレージは全部消える
このスクラップは2025/03/12にクローズされました