Об’єкти веб-сховища localStorage та sessionStorage дозволяють зберігати дані в браузері у вигляди пар ключ/значення.
Що цікаво, дані зберігаються навіть після оновлення сторінки (для sessionStorage) і після повного закриття і нового відкриття вікна браузера (для localStorage). Ми скоро перевіримо це на практиці.
Ми вже маємо cookies. Навіщо додаткові об’єкти?
- На відміну від файлів cookies, об’єкти веб-сховища не надсилаються на сервер із кожним запитом. Завдяки цьому ми можемо зберігати набагато більше даних. Більшість браузерів дозволяють принаймні 5 мегабайтів даних (або більше), користувач може навіть змінити цей об’єм.
- Крім того, на відміну від файлів cookies, сервер не може маніпулювати об’єктами сховища через HTTP-заголовки. Все зроблено на JavaScript.
- Сховище прив’язане до оригінального сайту (домен/протокол/порт). Таким чином, що різні протоколи або субдомени мають різні об’єкти зберігання, і не можуть отримати доступ до даних один одного.
Обидва об’єкти сховища забезпечують однакові методи та властивості:
setItem(key, value)– зберегти пару ключ/значення.getItem(key)– отримати значення за ключем.removeItem(key)– видалити дані за ключем.clear()– видалити все.key(index)– отримати ключ на заданій позиції.length– кількість збережених елементів.
Як ви можете бачити, це схоже на колекцію Map (setItem/getItem/removeItem), але також дозволяє отримати доступ за індексом за допомогою key(index).
Подивімося, як це працює.
Демонстрація роботи 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<localStorage.length; i++) {
let key = localStorage.key(i);
alert(`${key}: ${localStorage.getItem(key)}`);
}
Інший спосіб – використати цикл for key in localStorage, так само, як для звичайних об’єктів.
Він перебирає ключі, але також виводить кілька вбудованих властивостей, які нам не потрібні:
// невдала спроба
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 повертає лише ключі, які належать об’єкту, ігноруючи прототип.
Тільки рядки
Зверніть увагу, що і ключ, і значення мають бути рядками.
Якщо ми спробуємо використати будь-який інший тип, наприклад число або об’єкт, він автоматично перетвориться на рядок:
localStorage.user = {name: "John"};
alert(localStorage.user); // [object Object]
Однак ми можемо використати JSON для зберігання об’єктів:
localStorage.user = JSON.stringify({name: "Тарас"});
// через деякий час
let user = JSON.parse( localStorage.user );
alert( user.name ); // Тарас
Також можна перетворити весь об’єкт сховища на JSON рядок, наприклад, під час налагодження коду:
// додано параметри форматування до JSON.stringify, щоб об’єкт виглядав краще
alert( JSON.stringify(localStorage, null, 2) );
sessionStorage
Об’єкт sessionStorage використовується набагато рідше, ніж localStorage.
Властивості та методи ті самі, але можливості більш обмежені:
sessionStorageіснує лише на поточній вкладці браузера.- Інша вкладка з тією ж сторінкою матиме інше сховище.
- Але він використовується між iframes на одній вкладці (за умови, що це один сайт).