LocalStorage, sessionStorage

https://learn.javascript.ru/localstorage

Объекты веб-хранилища localStorage и sessionStorage позволяют хранить пары ключ/значение в браузере.

Что в них важно – данные, которые в них записаны, сохраняются после обновления страницы (в случае sessionStorage) и даже после перезапуска браузера (при использовании localStorage). Скоро мы это увидим.

Но ведь у нас уже есть куки. Зачем тогда эти объекты?

  • В отличие от куки, объекты веб-хранилища не отправляются на сервер при каждом запросе. Именно поэтому мы можем хранить гораздо больше данных. Большинство современных браузеров могут выделить как минимум 5 мегабайтов данных (или больше), и этот размер можно поменять в настройках.

  • Ещё одно отличие от куки – сервер не может манипулировать объектами хранилища через HTTP-заголовки. Всё делается при помощи JavaScript.

  • Хранилище привязано к источнику (домен/протокол/порт). Это значит, что разные протоколы или поддомены определяют разные объекты хранилища, и они не могут получить доступ к данным друг друга.

Объекты хранилища localStorage и sessionStorage предоставляют одинаковые методы и свойства:

  • setItem(key, value) – сохранить пару ключ/значение.

  • getItem(key) – получить данные по ключу key.

  • removeItem(key) – удалить данные с ключом key.

  • clear() – удалить всё.

  • key(index) – получить ключ на заданной позиции.

  • length – количество элементов в хранилище.

Как видим, интерфейс похож на Map (setItem/getItem/removeItem), но также позволяет получить доступ к элементу по индексу – key(index).

Давайте посмотрим, как это работает.

Основные особенности localStorage:

  • Этот объект один на все вкладки и окна в рамках источника (один и тот же домен/протокол/порт).

  • Данные не имеют срока давности, по которому истекают и удаляются. Сохраняются после перезапуска браузера и даже ОС.

Например, если запустить этот код…

…И закрыть/открыть браузер или открыть ту же страницу в другом окне, то можно получить данные следующим образом:

Нам достаточно находиться на том же источнике (домен/протокол/порт), при этом URL-путь может быть разным.

Объект localStorage доступен всем окнам из одного источника, поэтому, если мы устанавливаем данные в одном окне, изменения становятся видимыми в другом.

Также можно получать/записывать данные, как в обычный объект:

Это возможно по историческим причинам и, как правило, работает, но обычно не рекомендуется, потому что:

  1. Если ключ генерируется пользователем, то он может быть каким угодно, включая length или toString или другой встроенный метод localStorage. В этом случае getItem/setItem сработают нормально, а вот чтение/запись как свойства объекта не пройдут:

  2. Когда мы модифицируем данные, то срабатывает событие storage. Но это событие не происходит при записи без setItem, как свойства объекта. Мы увидим это позже в этой главе.

Методы, которые мы видим, позволяют читать/писать/удалять данные. А как получить все значения или ключи?

К сожалению, объекты веб-хранилища нельзя перебрать в цикле, они не итерируемы.

Но можно пройти по ним, как по обычным массивам:

Другой способ – использовать цикл, как по обычному объекту for key in localStorage.

Здесь перебираются ключи, но вместе с этим выводятся несколько встроенных полей, которые нам не нужны:

…Поэтому нам нужно либо отфильтровать поля из прототипа проверкой hasOwnProperty:

…Либо просто получить «собственные» ключи с помощью Object.keys, а затем при необходимости вывести их при помощи цикла:

Последнее работает, потому что Object.keys возвращает только ключи, принадлежащие объекту, игнорируя прототип.

Обратите внимание, что ключ и значение должны быть строками.

Если мы используем любой другой тип, например число или объект, то он автоматически преобразуется в строку:

Мы можем использовать JSON для хранения объектов:

Также возможно привести к строке весь объект хранилища, например для отладки:

Объект sessionStorage используется гораздо реже, чем localStorage.

Свойства и методы такие же, но есть существенные ограничения:

  • sessionStorage существует только в рамках текущей вкладки браузера.

    • Другая вкладка с той же страницей будет иметь другое хранилище.

    • Но оно разделяется между ифреймами на той же вкладке (при условии, что они из одного и того же источника).

  • Данные продолжают существовать после перезагрузки страницы, но не после закрытия/открытия вкладки.

Давайте посмотрим на это в действии.

Запустите этот код…

…И обновите страницу. Вы всё ещё можете получить данные:

…Но если вы откроете ту же страницу в другой вкладке и попробуете получить данные снова, то код выше вернёт null, что значит «ничего не найдено».

Так получилось, потому что sessionStorage привязан не только к источнику, но и к вкладке браузера. Поэтому sessionStorage используется нечасто.

Когда обновляются данные в localStorage или sessionStorage, генерируется событие storagearrow-up-right со следующими свойствами:

  • key – ключ, который обновился (null, если вызван .clear()).

  • oldValue – старое значение (null, если ключ добавлен впервые).

  • newValue – новое значение (null, если ключ был удалён).

  • url – url документа, где произошло обновление.

  • storageArea – объект localStorage или sessionStorage, где произошло обновление.

Важно: событие срабатывает на всех остальных объектах window, где доступно хранилище, кроме того окна, которое его вызвало.

Давайте уточним.

Представьте, что у вас есть два окна с одним и тем же сайтом. Хранилище localStorage разделяется между ними.

Вы можете открыть эту страницу в двух окнах браузера, чтобы проверить приведённый ниже код.

Теперь, если оба окна слушают window.onstorage, то каждое из них будет реагировать на обновления, произошедшие в другом окне.

Обратите внимание, что событие также содержит: event.url – url-адрес документа, в котором данные обновились.

Также event.storageArea содержит объект хранилища – событие одно и то же для sessionStorage и localStorage, поэтому event.storageArea ссылается на то хранилище, которое было изменено. Мы можем захотеть что-то записать в ответ на изменения.

Это позволяет разным окнам одного источника обмениваться сообщениями.

Современные браузеры также поддерживают Broadcast channel APIarrow-up-right специальный API для связи между окнами одного источника, он более полнофункциональный, но менее поддерживаемый. Существуют библиотеки (полифилы), которые эмулируют это API на основе localStorage и делают его доступным везде.

Объекты веб-хранилища localStorage и sessionStorage позволяют хранить пары ключ/значение в браузере.

  • key и value должны быть строками.

  • Лимит 5 Мб+, зависит от браузера.

  • Данные не имеют «времени истечения».

  • Данные привязаны к источнику (домен/протокол/порт).

localStorage

sessionStorage

Совместно используется между всеми вкладками и окнами с одинаковым источником

Разделяется в рамках вкладки браузера, среди ифреймов из того же источника

«Переживает» перезапуск браузера

«Переживает» перезагрузку страницы (но не закрытие вкладки)

API:

  • setItem(key, value) – сохранить пару ключ/значение.

  • getItem(key) – получить данные по ключу key.

  • removeItem(key) – удалить значение по ключу key.

  • clear() – удалить всё.

  • key(index) – получить ключ на заданной позиции.

  • length – количество элементов в хранилище.

  • Используйте Object.keys для получения всех ключей.

  • Можно обращаться к ключам как к обычным свойствам объекта, в этом случае событиеstorage не срабатывает.

Событие storage:

  • Срабатывает при вызове setItem, removeItem, clear.

  • Содержит все данные об произошедшем обновлении (key/oldValue/newValue), url документа и объект хранилища storageArea.

  • Срабатывает на всех объектах window, которые имеют доступ к хранилищу, кроме того, где оно было сгенерировано (внутри вкладки для sessionStorage, глобально для localStorage).

https://learn.javascript.ru/localstoragearrow-up-right

Last updated