В чем разница между localStorage и SessionStorage?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница Между localStorage и sessionStorage
Это хороший вопрос, который показывает понимание браузерного хранилища. Оба это механизмы для хранения данных на клиенте, но они используются в разных сценариях.
Основные Отличия
localStorage
- Время жизни: Неограниченно (пока пользователь не очистит)
- Область действия: Один браузер, один домен
- Размер: ~5-10 MB (зависит от браузера)
- Синхронизация: Синхронен (блокирует UI)
sessionStorage
- Время жизни: Только в течение сессии (закрытие вкладки = удаление)
- Область действия: Одна вкладка, один домен
- Размер: ~5 MB
- Синхронизация: Синхронен (блокирует UI)
Таблица Сравнения
┌──────────────────────┬──────────────────────┬────────────────────────┐
│ Параметр │ localStorage │ sessionStorage │
├──────────────────────┼──────────────────────┼────────────────────────┤
│ Время жизни │ Постоянно │ Пока открыта вкладка │
│ Область действия │ Весь браузер, домен │ Только эта вкладка │
│ Синхронизация между │ Да (storage event) │ Нет │
│ вкладками │ │ │
│ Когда очищается │ Вручную или в коде │ При закрытии вкладки │
│ Использование │ Долгосрочные данные │ Временные данные │
└──────────────────────┴──────────────────────┴────────────────────────┘
localStorage — Долгосрочное Хранилище
Пример: Сохранение Preferences
// Пользователь выбирает тему
function setTheme(theme: 'light' | 'dark') {
// Сохраняем в localStorage (помещается даже после перезагрузки)
localStorage.setItem('theme', theme);
document.body.setAttribute('data-theme', theme);
}
// При загрузке страницы (даже через неделю)
function initializeTheme() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.body.setAttribute('data-theme', savedTheme);
}
}
Типичные использования localStorage:
- Предпочтения пользователя (тема, язык, размер шрифта)
- Кеш данных (списки товаров, результаты поиска)
- Токены доступа (но НЕ рекомендуется!)
- Аналитика и отслеживание
Проблема с localStorage для токенов:
// ❌ Плохо — хранить JWT в localStorage
localStorage.setItem('authToken', jwtToken);
// Почему плохо:
// 1. XSS атака: вредоносный JavaScript может прочитать
const token = localStorage.getItem('authToken');
console.log(token); // Украдено!
// 2. localStorage доступен любому скрипту на странице
// 3. CSRF атаки могут использовать этот токен
Правильное хранилище для токенов: httpOnly cookies (не доступны из JavaScript).
sessionStorage — Временное Хранилище
Пример: Сохранение State Формы
// Пользователь заполняет сложную форму
function saveFormState(formId: string, formData: any) {
// Сохраняем в sessionStorage (если перезагрузит страницу — восстановим)
sessionStorage.setItem(`form_${formId}`, JSON.stringify(formData));
}
function restoreFormState(formId: string) {
const saved = sessionStorage.getItem(`form_${formId}`);
if (saved) {
return JSON.parse(saved);
}
return null;
}
// Если пользователь закроет вкладку — данные удалятся
// (что правильно — новая сессия, новые данные)
Типичные использования sessionStorage:
- Временные данные (страницу назад, поиск текущей сессии)
- State между страницами в одной сессии
- Данные, которые НЕ должны хранится после закрытия вкладки
- Флаги для UI (показывать tutorial или нет)
Практические Примеры
Пример 1: Multi-tab Синхронизация (localStorage)
// Вкладка 1: меняет тему
localStorage.setItem('theme', 'dark');
// Вкладка 2: слушает изменения
window.addEventListener('storage', (event) => {
if (event.key === 'theme') {
// event.newValue = 'dark'
applyTheme(event.newValue);
}
});
// Благодаря storage event, вкладка 2 узнает об изменении!
// sessionStorage этого НЕ поддерживает
Пример 2: Восстановление После Перезагрузки (localStorage)
// App.tsx
function useAuthToken() {
const [token, setToken] = useState<string | null>(() => {
// При загрузке приложения восстанавливаем токен
return localStorage.getItem('token');
});
const saveToken = (newToken: string) => {
setToken(newToken);
localStorage.setItem('token', newToken);
};
const logout = () => {
setToken(null);
localStorage.removeItem('token');
};
return { token, saveToken, logout };
}
Пример 3: Сохранение Drafts (sessionStorage)
// Пользователь пишет комментарий
function saveDraft(postId: string, draft: string) {
sessionStorage.setItem(`draft_${postId}`, draft);
}
function publishComment(postId: string, draft: string) {
// После публикации удаляем draft
sessionStorage.removeItem(`draft_${postId}`);
// Отправляем на сервер
api.postComment(postId, draft);
}
function discardDraft(postId: string) {
sessionStorage.removeItem(`draft_${postId}`);
}
// Если пользователь закроет вкладку — draft удалится
// (это безопасно, потому что это временные данные)
Важные Моменты
1. Оба синхронны
// ❌ Плохо — это блокирует UI
for (let i = 0; i < 1000000; i++) {
localStorage.setItem(`key_${i}`, `value_${i}`);
}
// Браузер "зависнет" на время
// Пользователь не может кликать, скролить и т.д.
Решение: используй IndexedDB для больших объёмов данных.
2. Размер ограничен
// localStorage есть лимит ~5MB
const data = 'x'.repeat(6 * 1024 * 1024); // 6 MB
try {
localStorage.setItem('bigData', data);
} catch (e) {
console.log('QuotaExceededError'); // Превышен лимит
}
3. Только строки
// ❌ localStorage хранит только строки
localStorage.setItem('obj', { name: 'John' });
// Результат: '[object Object]'
// ✅ Правильно
localStorage.setItem('obj', JSON.stringify({ name: 'John' }));
const obj = JSON.parse(localStorage.getItem('obj'));
4. sessionStorage НЕ синхронизируется между вкладками
// Вкладка 1
sessionStorage.setItem('data', 'hello');
// Вкладка 2
console.log(sessionStorage.getItem('data')); // null!
// sessionStorage изолирована по вкладкам
// Если нужна синхронизация → используй localStorage + storage event
Когда Использовать Что
Используй localStorage:
- Предпочтения пользователя (будут при следующем визите)
- Кеш данных (можешь использовать неделями)
- Долгосрочные данные (пароли и токены — ТОЛЬКО в httpOnly cookies!)
Используй sessionStorage:
- Временные данные (пока открыта вкладка)
- State в multi-step форм (при перезагрузке обновится)
- Данные, которые НЕ должны быть "липкими" (не должны сохраняться после закрытия вкладки)
Лучшие Практики
// Оберни в try-catch (может быть ошибка квоты)
function safeSetStorage(storage: Storage, key: string, value: string) {
try {
storage.setItem(key, value);
} catch (e) {
if (e instanceof DOMException && e.code === 22) {
// QuotaExceededError
console.log('Storage is full');
// Очисти старые данные
cleanupOldData(storage);
}
}
}
// Не забывай правила
function getData(key: string) {
const data = localStorage.getItem(key);
if (!data) return null;
try {
return JSON.parse(data);
} catch (e) {
console.error('Failed to parse stored data');
return null;
}
}
Альтернативы
IndexedDB — для больших объёмов данных
// асинхронно, поддерживает индексы, транзакции
const db = new IndexedDB('myApp');
await db.store('users').add({ id: 1, name: 'John' });
Service Worker Cache — для кеша сетевых запросов
// Кеш HTTP ответов
await caches.open('my-cache').then(cache => {
cache.add('/api/users');
});
Заключение
localStorage: для долгосрочных данных (дни, недели, месяцы) sessionStorage: для временных данных (текущая сессия)
Оба синхронны и имеют ограничения, поэтому для больших данных используй IndexedDB.
И помни: НИКОГДА не храни чувствительные данные (JWT, пароли) в localStorage. Используй httpOnly cookies.