Чем отличается LocalStorage от SessionStorage?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
LocalStorage vs SessionStorage
Это классический вопрос на интервью, который проверяет понимание браузерного хранилища данных. За 10+ лет я видел множество ошибок в проектах из-за неправильного выбора между ними.
Таблица сравнения
| Характеристика | LocalStorage | SessionStorage |
|---|---|---|
| Время жизни | До явного удаления | До закрытия вкладки/браузера |
| Область видимости | Все вкладки одного домена | Только текущая вкладка |
| Объём | 5-10 MB (в зависимости от браузера) | 5-10 MB |
| Используется для | Стабильные данные | Временные данные сессии |
| Производительность | Синхронный (блокирует UI) | Синхронный (блокирует UI) |
LocalStorage
localStorage хранит данные постоянно, пока пользователь или разработчик их явно не удалит. Доступен всем вкладкам на одном домене.
// Сохранение данных
localStorage.setItem("username", "John");
localStorage.setItem("preferences", JSON.stringify({ theme: "dark", lang: "ru" }));
// Получение данных
const username = localStorage.getItem("username"); // "John"
const preferences = JSON.parse(localStorage.getItem("preferences")); // { theme: "dark", lang: "ru" }
// Проверка наличия
if (localStorage.getItem("token")) {
console.log("Пользователь авторизован");
}
// Удаление
localStorage.removeItem("username");
localStorage.clear(); // удалить всё
// Итерация
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
console.log(key, localStorage.getItem(key));
}
Когда использовать:
- Сохранение предпочтений пользователя (тема, язык)
- Кеш данных, которые меняются редко
- Токены авторизации (с осторожностью!)
- История поиска, недавние действия
// Сохранение темы
function useTheme() {
const [theme, setTheme] = useState<"light" | "dark">(() => {
const saved = localStorage.getItem("theme");
return (saved as "light" | "dark") || "light";
});
const toggleTheme = useCallback(() => {
setTheme(prev => {
const next = prev === "light" ? "dark" : "light";
localStorage.setItem("theme", next);
return next;
});
}, []);
return { theme, toggleTheme };
}
SessionStorage
sessionStorage хранит данные только для текущей сессии браузера. Когда пользователь закрывает вкладку или браузер, данные удаляются. Каждая вкладка имеет свой отдельный sessionStorage.
// Использование идентично localStorage
sessionStorage.setItem("currentStep", "2");
const step = sessionStorage.getItem("currentStep"); // "2"
// Удаление
sessionStorage.removeItem("currentStep");
sessionStorage.clear();
Когда использовать:
- Сохранение состояния многошагового процесса (форма, гайд)
- Временные данные текущей сессии
- Данные, которые нужны между переходами по страницам
- Кеш, который должен очиститься при закрытии вкладки
// Многошаговая форма
function useFormStep() {
const [step, setStep] = useState<number>(() => {
const saved = sessionStorage.getItem("formStep");
return saved ? parseInt(saved) : 1;
});
const goToStep = useCallback((nextStep: number) => {
setStep(nextStep);
sessionStorage.setItem("formStep", String(nextStep));
}, []);
const resetForm = useCallback(() => {
setStep(1);
sessionStorage.removeItem("formStep");
}, []);
return { step, goToStep, resetForm };
}
Ключевые различия на примерах
1. Закрытие браузера
// В одной вкладке
localStorage.setItem("persistent", "data1");
sessionStorage.setItem("temporary", "data2");
// Пользователь закрывает браузер
// sessionStorage очищается автоматически
// localStorage остаётся
// После переоткрытия браузера
console.log(localStorage.getItem("persistent")); // "data1" ✅
console.log(sessionStorage.getItem("temporary")); // null ❌
2. Несколько вкладок
// Вкладка 1
localStorage.setItem("user", "John");
sessionStorage.setItem("cart", "[item1, item2]");
// Вкладка 2
console.log(localStorage.getItem("user")); // "John" ✅ видно в обеих вкладках
console.log(sessionStorage.getItem("cart")); // null ❌ нет, это отдельное хранилище
// SessionStorage для каждой вкладки — свой
sessionStorage.setItem("cart", "[item3]");
// Вкладка 1 всё ещё видит свои данные
console.log(sessionStorage.getItem("cart")); // "[item1, item2]"
Обработка событий Storage
Когда данные изменяются в localStorage, другие вкладки/окна получают событие:
// Вкладка 1
localStorage.setItem("notification", "New message");
// Вкладка 2 слышит событие
window.addEventListener("storage", (event) => {
if (event.key === "notification") {
console.log("Получено новое сообщение:", event.newValue);
showNotification(event.newValue);
}
});
// ВАЖНО: SessionStorage не генерирует события storage!
// Это раздельное хранилище для каждой вкладки
Практические примеры в React
useLocalStorage хук
function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
const setValue = useCallback((value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
}, [key, storedValue]);
return [storedValue, setValue] as const;
}
// Использование
function UserPreferences() {
const [theme, setTheme] = useLocalStorage<"light" | "dark">("theme", "light");
return (
<button onClick={() => setTheme(t => t === "light" ? "dark" : "light")}>
Current theme: {theme}
</button>
);
}
Безопасность
⚠️ ВАЖНО: Никогда не сохраняй чувствительные данные в localStorage!
// ❌ НИКОГДА ТАК
localStorage.setItem("token", authToken); // Уязвимо для XSS атак
localStorage.setItem("password", password); // Никогда!
// ✅ Используй HttpOnly cookies для токенов
// Сервер устанавливает в заголовке Set-Cookie с флагом HttpOnly
// Браузер автоматически отправляет в каждом запросе
// JavaScript не может получить доступ (защита от XSS)
Размеры и лимиты
function getStorageSize() {
let total = 0;
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
total += key.length + (value ? value.length : 0);
}
console.log(`LocalStorage использует ~${(total / 1024).toFixed(2)} KB`);
}
// Типичный лимит: 5-10 MB
// Если превышить, бросится исключение QuotaExceededError
Альтернативы
- IndexedDB — для больших объёмов данных (>100 MB)
- HttpOnly Cookies — для токенов авторизации
- sessionStorage — для временных данных
- localStorage — для стабильных настроек
Заключение
Выбор прост:
localStorage— если данные должны сохраниться после закрытия браузераsessionStorage— если данные нужны только в текущей сессии
Это базовое правило решит 90% случаев. Помни о безопасности и лимитах хранилища!