LocalStorage, SessionStorage
LocalStorage, SessionStorage
Объекты веб-хранилища localStorage и sessionStorage позволяют хранить пары ключ/значение в браузере.
Что в них важно – данные, которые в них записаны, сохраняются после обновления страницы (в случае sessionStorage) и даже после перезапуска браузера (при использовании localStorage). Скоро мы это увидим.
Объекты хранилища localStorage и sessionStorage предоставляют одинаковые методы и свойства:
- setItem(key, value) – сохранить пару ключ/значение.
- getItem(key) – получить данные по ключу key.
- removeItem(key) – удалить данные с ключом key.
- clear() – удалить всё.
- key(index) – получить ключ на заданной позиции.
- length – количество элементов в хранилище.
Демо localStorage
Основные особенности localStorage:
- Этот объект один на все вкладки и окна в рамках источника (один и тот же домен/протокол/порт).
- Данные не имеют срока давности, по которому истекают и удаляются. Сохраняются после перезапуска браузера и даже ОС.
Например, если запустить этот код…
localStorage.setItem('test', 1);
…И закрыть/открыть браузер или открыть ту же страницу в другом окне, то можно получить данные следующим образом:
alert( localStorage.getItem('test') ); // 1
Нам достаточно находиться на том же источнике (домен/протокол/порт), при этом URL-путь может быть разным.
Объект localStorage доступен всем окнам из одного источника, поэтому, если мы устанавливаем данные в одном окне, изменения становятся видимыми в другом.
Доступ как к обычному объекту
Также можно получать/записывать данные, как в обычный объект:
// установить значение для ключа
localStorage.test = 2;
// получить значение по ключу
alert( localStorage.test ); // 2
// удалить ключ
delete localStorage.test;
Это возможно по историческим причинам и, как правило, работает, но обычно не рекомендуется, потому что:
Если ключ генерируется пользователем, то он может быть каким угодно, включая length или toString или другой встроенный метод localStorage. В этом случае getItem/setItem сработают нормально, а вот чтение/запись как свойства объекта не пройдут:
let key = 'length';
localStorage[key] = 5; // Ошибка, невозможно установить length
Когда мы модифицируем данные, то срабатывает событие storage. Но это событие не происходит при записи без setItem, как свойства объекта. Мы увидим это позже в этой главе.
Перебор ключей
Методы, которые мы видим, позволяют читать/писать/удалять данные. А как получить все значения или ключи?
К сожалению, объекты веб-хранилища нельзя перебрать в цикле, они не итерируемы.
Но можно пройти по ним, как по обычным массивам:
for(let i=0; i
Другой способ – использовать цикл, как по обычному объекту for key in localStorage.
Здесь перебираются ключи, но вместе с этим выводятся несколько встроенных полей, которые нам не нужны:
// bad try
for(let key in localStorage) {
alert(key); // покажет getItem, setItem и другие встроенные свойства
}
…Поэтому нам нужно либо отфильтровать поля из прототипа проверкой hasOwnProperty:
for(let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue; // пропустит такие ключи, как "setItem", "getItem" и так далее
}
alert(`${key}: ${localStorage.getItem(key)}`);
}
…Либо просто получить «собственные» ключи с помощью Object.keys, а затем при необходимости вывести их при помощи цикла:
let keys = Object.keys(localStorage);
for(let key of keys) {
alert(`${key}: ${localStorage.getItem(key)}`);
}
Последнее работает, потому что Object.keys возвращает только ключи, принадлежащие объекту, игнорируя прототип.
Только строки
Обратите внимание, что ключ и значение должны быть строками.
Если мы используем любой другой тип, например число или объект, то он автоматически преобразуется в строку:
sessionStorage.user = {name: "John"};
alert(sessionStorage.user); // [object Object]
Мы можем использовать JSON для хранения объектов:
sessionStorage.user = JSON.stringify({name: "John"});
// немного позже
let user = JSON.parse( sessionStorage.user );
alert( user.name ); // John
Также возможно привести к строке весь объект хранилища, например для отладки:
// для JSON.stringify добавлены параметры форматирования, чтобы объект выглядел лучше
alert( JSON.stringify(localStorage, null, 2) );
sessionStorage
Объект sessionStorage используется гораздо реже, чем localStorage.
Свойства и методы такие же, но есть существенные ограничения:
sessionStorage существует только в рамках текущей вкладки браузера.
Другая вкладка с той же страницей будет иметь другое хранилище.
Но оно разделяется между ифреймами на той же вкладке (при условии, что они из одного и того же источника).
Данные продолжают существовать после перезагрузки страницы, но не после закрытия/открытия вкладки.
Давайте посмотрим на это в действии.
Запустите этот код…
sessionStorage.setItem('test', 1);
…И обновите страницу. Вы всё ещё можете получить данные:
alert( sessionStorage.getItem('test') ); // после обновления: 1
…Но если вы откроете ту же страницу в другой вкладке и попробуете получить данные снова, то код выше вернёт null, что значит «ничего не найдено».
Так получилось, потому что sessionStorage привязан не только к источнику, но и к вкладке браузера. Поэтому sessionStorage используется нечасто.
Событие storage
Когда обновляются данные в localStorage или sessionStorage, генерируется событие storage со следующими свойствами:
key – ключ, который обновился (null, если вызван .clear()).
oldValue – старое значение (null, если ключ добавлен впервые).
newValue – новое значение (null, если ключ был удалён).
url – url документа, где произошло обновление.
storageArea – объект localStorage или sessionStorage, где произошло обновление.
Важно: событие срабатывает на всех остальных объектах window, где доступно хранилище, кроме того окна, которое его вызвало.
Давайте уточним.
Представьте, что у вас есть два окна с одним и тем же сайтом. Хранилище localStorage разделяется между ними.
Вы можете открыть эту страницу в двух окнах браузера, чтобы проверить приведённый ниже код.
Теперь, если оба окна слушают window.onstorage, то каждое из них будет реагировать на обновления, произошедшие в другом окне.
// срабатывает при обновлениях, сделанных в том же хранилище из других документов
window.onstorage = event => {
if (event.key != 'now') return;
alert(event.key + ':' + event.newValue + " at " + event.url);
};
localStorage.setItem('now', Date.now());
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.