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
доступен всем окнам из одного источника, поэтому, если мы устанавливаем данные в одном окне, изменения становятся видимыми в другом.
Также можно получать/записывать данные, как в обычный объект:
Это возможно по историческим причинам и, как правило, работает, но обычно не рекомендуется, потому что:
Если ключ генерируется пользователем, то он может быть каким угодно, включая
length
илиtoString
или другой встроенный методlocalStorage
. В этом случаеgetItem/setItem
сработают нормально, а вот чтение/запись как свойства объекта не пройдут:Когда мы модифицируем данные, то срабатывает событие
storage
. Но это событие не происходит при записи безsetItem
, как свойства объекта. Мы увидим это позже в этой главе.
Методы, которые мы видим, позволяют читать/писать/удалять данные. А как получить все значения или ключи?
К сожалению, объекты веб-хранилища нельзя перебрать в цикле, они не итерируемы.
Но можно пройти по ним, как по обычным массивам:
Другой способ – использовать цикл, как по обычному объекту for key in localStorage
.
Здесь перебираются ключи, но вместе с этим выводятся несколько встроенных полей, которые нам не нужны:
…Поэтому нам нужно либо отфильтровать поля из прототипа проверкой hasOwnProperty
:
…Либо просто получить «собственные» ключи с помощью Object.keys, а затем при необходимости вывести их при помощи цикла:
Последнее работает, потому что Object.keys
возвращает только ключи, принадлежащие объекту, игнорируя прототип.
Обратите внимание, что ключ и значение должны быть строками.
Если мы используем любой другой тип, например число или объект, то он автоматически преобразуется в строку:
Мы можем использовать JSON
для хранения объектов:
Также возможно привести к строке весь объект хранилища, например для отладки:
Объект sessionStorage
используется гораздо реже, чем localStorage
.
Свойства и методы такие же, но есть существенные ограничения:
sessionStorage
существует только в рамках текущей вкладки браузера.Другая вкладка с той же страницей будет иметь другое хранилище.
Но оно разделяется между ифреймами на той же вкладке (при условии, что они из одного и того же источника).
Данные продолжают существовать после перезагрузки страницы, но не после закрытия/открытия вкладки.
Давайте посмотрим на это в действии.
Запустите этот код…
…И обновите страницу. Вы всё ещё можете получить данные:
…Но если вы откроете ту же страницу в другой вкладке и попробуете получить данные снова, то код выше вернёт null
, что значит «ничего не найдено».
Так получилось, потому что sessionStorage
привязан не только к источнику, но и к вкладке браузера. Поэтому sessionStorage
используется нечасто.
Когда обновляются данные в localStorage
или sessionStorage
, генерируется событие storage со следующими свойствами:
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 API специальный API для связи между окнами одного источника, он более полнофункциональный, но менее поддерживаемый. Существуют библиотеки (полифилы), которые эмулируют это API на основе localStorage
и делают его доступным везде.
Объекты веб-хранилища localStorage
и sessionStorage
позволяют хранить пары ключ/значение в браузере.
key
иvalue
должны быть строками.Лимит 5 Мб+, зависит от браузера.
Данные не имеют «времени истечения».
Данные привязаны к источнику (домен/протокол/порт).
|
|
Совместно используется между всеми вкладками и окнами с одинаковым источником | Разделяется в рамках вкладки браузера, среди ифреймов из того же источника |
«Переживает» перезапуск браузера | «Переживает» перезагрузку страницы (но не закрытие вкладки) |
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
).
Last updated