localStorage и sessionStorage в JavaScript: понятное практическое руководство

localStorage и sessionStorage в JavaScript: понятное практическое руководство

localStorage и sessionStorage в JavaScript: понятное практическое руководство

Зачем нужен Web Storage и чем полезен localStorage в JavaScript

Web Storage API даёт два простых механизма для хранения данных на стороне клиента: localStorage и sessionStorage. Оба — это ключ‑значение (только строки), синхронные, очень быстрые и не требуют сервера. Классические сценарии: сохранение темы оформления, последнего открытого шага мастера, содержимого корзины, флагов «уже показывал подсказку» и др.

  • localStorage — общая «память» для домена. Данные живут между перезапусками браузера, до явного удаления.
  • sessionStorage — память текущей вкладки. Очищается при закрытии вкладки (или вкладочного контекста).
  • Быстрый старт: основные операции

    // Сохранить строку
    localStorage.setItem('theme', 'dark');
    
    // Прочитать
    const theme = localStorage.getItem('theme'); // 'dark'
    
    // Удалить ключ
    localStorage.removeItem('theme');
    
    // Очистить всё хранилище текущего домена
    localStorage.clear();
    
    // Количество записей
    console.log(localStorage.length);
    

    У sessionStorage тот же API: setItem, getItem, removeItem, clear и свойство length.

    Хранение объектов: JSON.stringify и JSON.parse

    Web Storage хранит только строки. Для объектов используйте JSON:

    const user = { id: 42, name: 'Alice', roles: ['admin', 'author'] };
    localStorage.setItem('user', JSON.stringify(user));
    
    try {
      const parsed = JSON.parse(localStorage.getItem('user'));
      console.log(parsed.name); // 'Alice'
    } catch (e) {
      console.warn('Некорректный JSON в localStorage');
    }
    

    Совет: добавляйте неймспейсы к ключам (например, app:cart), чтобы избежать конфликтов с чужими скриптами того же домена.

    Проверка доступности и обработка исключений

    В приватных режимах, при политике безопасности или переполнении квоты операции могут бросать исключения. Делайте защитные проверки:

    const storageAvailable = (() => {
      try {
        const k = '__test__' + Math.random();
        localStorage.setItem(k, '1');
        localStorage.removeItem(k);
        return true;
      } catch (_) {
        return false;
      }
    })();
    
    function safeSet(key, value) {
      if (!storageAvailable) return false;
      try {
        localStorage.setItem(key, value);
        return true;
      } catch (e) {
        console.warn('Не удалось записать в localStorage:', e);
        return false;
      }
    }
    

    Лимиты обычно 5–10 МБ на домен. Не храните большие бинарные строки и чувствительные данные (логины, токены).

    TTL (время жизни): делаем «устаревающие» записи

    По умолчанию записи не имеют срока жизни. Добавим TTL вручную — пригодится для кэшей запросов или баннеров «показать раз в сутки».

    function saveWithTTL(key, value, ttlMs) {
      const payload = { value, expires: Date.now() + ttlMs };
      localStorage.setItem(key, JSON.stringify(payload));
    }
    
    function loadWithTTL(key) {
      const raw = localStorage.getItem(key);
      if (!raw) return null;
      try {
        const data = JSON.parse(raw);
        if (data.expires && Date.now() > data.expires) {
          localStorage.removeItem(key);
          return null;
        }
        return data.value;
      } catch (_) {
        return null;
      }
    }
    
    // Пример: кэш ответа на 10 минут
    saveWithTTL('news:list', [{ id: 1, title: 'Hi' }], 10 * 60 * 1000);
    const cached = loadWithTTL('news:list');
    

    Удобная обёртка с неймспейсом

    Мини‑хелпер, который сериализует/десериализует и избегает конфликтов ключей:

    function createStore(prefix = 'app:') {
      return {
        set(key, val) {
          localStorage.setItem(prefix + key, JSON.stringify(val));
        },
        get(key, fallback = null) {
          const raw = localStorage.getItem(prefix + key);
          if (raw === null) return fallback;
          try { return JSON.parse(raw); } catch (_) { return fallback; }
        },
        remove(key) {
          localStorage.removeItem(prefix + key);
        }
      };
    }
    
    const store = createStore('demo:');
    store.set('settings', { theme: 'dark' });
    console.log(store.get('settings')); // { theme: 'dark' }
    

    Синхронизация между вкладками: событие storage

    Когда одна вкладка меняет localStorage, другие вкладки того же домена получают событие storage. Это удобно, чтобы синхронизировать тему, авторизацию, фичефлаги.

    // Синхронизация темы между вкладками
    window.addEventListener('storage', (e) => {
      if (e.key === 'theme') {
        document.documentElement.dataset.theme = e.newValue || 'light';
      }
    });
    
    // Где-то в UI:
    function toggleTheme() {
      const cur = localStorage.getItem('theme') === 'dark' ? 'light' : 'dark';
      localStorage.setItem('theme', cur);
    }
    

    Важно: событие не срабатывает в той вкладке, где изменение произошло, — только в других открытых вкладках/окнах.

    Чем sessionStorage отличается на практике

    sessionStorage изолирован по вкладкам. Хорош для временных черновиков форм, состояний мастера или «реферальных» меток в рамках одного визита:

    // Счётчик действий для этой вкладки
    const clicks = Number(sessionStorage.getItem('clicks') || 0) + 1;
    sessionStorage.setItem('clicks', String(clicks));
    console.log('Кликов в этой вкладке:', clicks);
    
    // Метка вкладки (удобно для отладки)
    if (!sessionStorage.getItem('tabId')) {
      sessionStorage.setItem('tabId', (crypto?.randomUUID?.() || Date.now().toString(36)));
    }
    

    Безопасность и ограничения

  • Не храните секреты (токены, пароли). При XSS злоумышленник прочитает Web Storage.
  • Объём ограничен, API синхронный — не кладите большие данные и не вызывайте операции в горячих циклах рендера.
  • Данные доступны только тому же протоколу/домену/порту.
  • Чек‑лист лучших практик

  • Используйте неймспейсы в ключах: app:feature:flag.
  • Сериализуйте через JSON и обрабатывайте ошибки JSON.parse.
  • Добавляйте TTL для кэшей и временных данных.
  • Проверяйте доступность хранилища и ловите исключения квоты.
  • Синхронизируйте важные состояния через событие storage.
  • Не храните чувствительные данные, позаботьтесь о защите от XSS.
  • Итоги

    localStorage в JavaScript — простой и мощный инструмент для клиентского состояния, а sessionStorage идеален для данных в рамках одной вкладки. Используйте JSON, TTL‑паттерн, неймспейсы и событие storage — так вы получите быстрый, предсказуемый и устойчивый к ошибкам слой хранения.

    Хотите уверенно применять эти техники в реальных проектах и закрепить всё на практике? Загляните в курс Полный практический путь по JavaScript: от нуля до уверенного уровня — много задач, разборов и проектов для прокачки навыков.

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий