ДокументацияJavaScriptlocalStorage и sessionStorage: сохранение данных в браузере
Начальный 8 мин чтения

localStorage и sessionStorage: сохранение данных в браузере

localStorage и sessionStorage в JavaScript — сохранение данных в браузере, отличия, методы setItem/getItem/removeItem, хранение объектов, сроки жизни и ограничения.

localStoragesessionStorageWeb Storageсохранение данныхбраузерJavaScript

Что такое Web Storage

localStorage и sessionStorage — механизмы браузера для хранения данных в виде пар «ключ-значение». Оба хранят только строки. Доступны через объект window.

localStorage vs sessionStorage

СвойствоlocalStoragesessionStorage
Срок жизнибессрочно (пока не удалить)до закрытия вкладки
Область видимостивсе вкладки одного источникатолько текущая вкладка
Объём~5-10 МБ~5-10 МБ
Тип данныхтолько строкитолько строки

«Источник» — это комбинация протокол + домен + порт. http://example.com и https://example.com — разные источники.

Базовые методы

Оба хранилища имеют одинаковый API:

// Сохранить
localStorage.setItem('theme', 'dark')
localStorage.setItem('lang', 'ru')

// Прочитать
localStorage.getItem('theme') // 'dark'
localStorage.getItem('unknown') // null

// Удалить один ключ
localStorage.removeItem('theme')

// Очистить всё
localStorage.clear()

// Количество записей
localStorage.length // 1

// Получить ключ по индексу
localStorage.key(0) // 'lang'

Краткая запись

Можно обращаться как к свойствам объекта:

localStorage.theme = 'dark'        // set
console.log(localStorage.theme)    // 'dark'
delete localStorage.theme          // remove

Но setItem/getItem предпочтительнее — безопаснее и нагляднее.

Хранение объектов

Хранилище работает только со строками. Объекты и массивы нужно сериализовать:

const settings = { theme: 'dark', fontSize: 16, lang: 'ru' }

// Сохранить
localStorage.setItem('settings', JSON.stringify(settings))

// Прочитать
const saved = JSON.parse(localStorage.getItem('settings'))
console.log(saved.theme) // 'dark'

Если данных нет — getItem вернёт null, и JSON.parse(null) вернёт null. Безопасное чтение:

function loadSettings() {
  const raw = localStorage.getItem('settings')
  return raw ? JSON.parse(raw) : { theme: 'light', fontSize: 14, lang: 'ru' }
}

sessionStorage — данные на время сессии

// Сохранить данные формы, чтобы не потерять при обновлении
sessionStorage.setItem('draft-title', 'Моя статья')
sessionStorage.setItem('draft-content', 'Текст статьи...')

// При загрузке страницы — восстановить
const title = sessionStorage.getItem('draft-title')
if (title) {
  document.querySelector('input').value = title
}

При закрытии вкладки данные sessionStorage исчезнут. Дублирование вкладки копирует sessionStorage, но новая вкладка получает собственную копию.

Практические примеры

Сохранение темы

function applyTheme() {
  const theme = localStorage.getItem('theme') || 'light'
  document.documentElement.classList.toggle('dark', theme === 'dark')
}

function toggleTheme() {
  const current = localStorage.getItem('theme') || 'light'
  const next = current === 'light' ? 'dark' : 'light'
  localStorage.setItem('theme', next)
  applyTheme()
}

applyTheme()

Сохранение токена авторизации

function saveToken(token) {
  localStorage.setItem('auth_token', token)
}

function getToken() {
  return localStorage.getItem('auth_token')
}

function logout() {
  localStorage.removeItem('auth_token')
}

Для безопасности токенов лучше использовать sessionStorage (исчезнет при закрытии) или httpOnly cookies.

Корзина покупок

function getCart() {
  const raw = localStorage.getItem('cart')
  return raw ? JSON.parse(raw) : []
}

function addToCart(item) {
  const cart = getCart()
  const existing = cart.find(i => i.id === item.id)

  if (existing) {
    existing.qty += 1
  } else {
    cart.push({ ...item, qty: 1 })
  }

  localStorage.setItem('cart', JSON.stringify(cart))
}

function removeFromCart(id) {
  const cart = getCart().filter(i => i.id !== id)
  localStorage.setItem('cart', JSON.stringify(cart))
}

Недавно просмотренные

function addToRecent(item, max = 10) {
  const recent = JSON.parse(localStorage.getItem('recent') || '[]')
  const filtered = recent.filter(i => i.id !== item.id)
  filtered.unshift(item)
  localStorage.setItem('recent', JSON.stringify(filtered.slice(0, max)))
}

function getRecent() {
  return JSON.parse(localStorage.getItem('recent') || '[]')
}

Событие storage

Когда данные меняются в одной вкладке, другие вкладки того же источника получают событие storage:

window.addEventListener('storage', (event) => {
  console.log('Ключ:', event.key)
  console.log('Старое значение:', event.oldValue)
  console.log('Новое значение:', event.newValue)
  console.log('URL:', event.url)
})

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

Полезная обёртка

const storage = {
  get(key, defaultValue = null) {
    const raw = localStorage.getItem(key)
    if (raw === null) return defaultValue
    try {
      return JSON.parse(raw)
    } catch {
      return raw
    }
  },

  set(key, value) {
    localStorage.setItem(key, JSON.stringify(value))
  },

  remove(key) {
    localStorage.removeItem(key)
  },

  clear() {
    localStorage.clear()
  },
}

storage.set('user', { name: 'Анна', age: 25 })
storage.get('user')           // { name: 'Анна', age: 25 }
storage.get('unknown', {})   // {} — значение по умолчанию

Ограничения

  • Только строки — объекты через JSON.stringify/JSON.parse
  • ~5-10 МБ — точный лимит зависит от браузера
  • Синхронный API — блокирует основной поток. Для больших объёмов используйте IndexedDB
  • Доступен из любого кода — XSS-атака может прочитать все данные. Не храните пароли, токены (лучше httpOnly cookies), персональные данные без шифрования
  • Не работает в приватном режиме в некоторых браузерах — может выбросить исключение

Безопасная запись:

function safeSetItem(key, value) {
  try {
    localStorage.setItem(key, value)
  } catch (error) {
    console.warn('localStorage недоступен:', error)
  }
}

Итог

  • localStorage — бессрочное хранение, sessionStorage — до закрытия вкладки
  • Только строки — объекты через JSON.stringify/JSON.parse
  • Событие storage — для синхронизации между вкладками
  • Не храните чувствительные данные — localStorage доступен из JavaScript
  • Для больших объёмов и структурированных данных используйте IndexedDB