L65 - localStorage y sessionStorage
🧠 Concepto
Section titled “🧠 Concepto”localStorage y sessionStorage son APIs del navegador que permiten almacenar datos de forma persistente en el cliente (en el disco del usuario). Ambas forman parte de la Web Storage API y proporcionan un almacenamiento clave-valor (strings) con un límite de ~5MB por dominio.
💻 localStorage vs sessionStorage
Section titled “💻 localStorage vs sessionStorage”| Característica | localStorage | sessionStorage |
|---|---|---|
| Persistencia | Persiste hasta que se borre manualmente | Se borra al cerrar la pestaña/navegador |
| Ámbito | Mismo origen (protocolo + dominio + puerto) | Mismo origen + misma pestaña |
| Ventanas/pestañas | Compartido entre todas las pestañas del mismo origen | Aislado por pestaña |
| Duración | Ilimitada (hasta borrado manual) | Solo mientras dure la sesión de la pestaña |
💻 Métodos básicos
Section titled “💻 Métodos básicos”// GuardarlocalStorage.setItem('nombre', 'Ana');localStorage.setItem('edad', '25');
// Leerconst nombre = localStorage.getItem('nombre'); // 'Ana'const edad = localStorage.getItem('edad'); // '25'const noExiste = localStorage.getItem('fake'); // null
// Eliminar unolocalStorage.removeItem('edad');
// Limpiar todolocalStorage.clear();
// Número de elementosconsole.log(localStorage.length); // 0 después de clear⚠️ Todo se almacena como string. Si guardas un número, lo recuperarás como string.
📝 Almacenar objetos
Section titled “📝 Almacenar objetos”Como solo acepta strings, hay que serializar con JSON:
const usuario = { id: 1, nombre: 'Ana', preferencias: { tema: 'oscuro', idioma: 'es' }};
// Guardar (serializar)localStorage.setItem('usuario', JSON.stringify(usuario));
// Recuperar (deserializar)const datos = localStorage.getItem('usuario');if (datos) { const usuarioRecuperado = JSON.parse(datos); console.log(usuarioRecuperado.preferencias.tema); // 'oscuro'}Patrón seguro
Section titled “Patrón seguro”function guardarStorage(clave, valor) { try { localStorage.setItem(clave, JSON.stringify(valor)); return true; } catch (e) { console.error('Error al guardar en localStorage:', e); return false; }}
function obtenerStorage(clave) { try { const datos = localStorage.getItem(clave); return datos ? JSON.parse(datos) : null; } catch (e) { console.error('Error al leer localStorage:', e); return null; }}🎯 Evento storage
Section titled “🎯 Evento storage”Cuando se modifica localStorage (no sessionStorage) y hay otra pestaña abierta del mismo origen, se dispara el evento storage:
// Escuchar cambios en otras pestañaswindow.addEventListener('storage', (event) => { console.log('Clave modificada:', event.key); console.log('Valor anterior:', event.oldValue); console.log('Valor nuevo:', event.newValue); console.log('URL de origen:', event.url); console.log('Storage area:', event.storageArea);});
// Ejemplo: sincronizar tema entre pestañaswindow.addEventListener('storage', (e) => { if (e.key === 'tema') { document.body.className = e.newValue; }});📝 sessionStorage
Section titled “📝 sessionStorage”Idéntica API, pero los datos se borran al cerrar la pestaña:
// Guardar datos temporales (no sobreviven al cierre)sessionStorage.setItem('carrito', JSON.stringify({ items: ['producto1', 'producto2'], total: 150}));
// Útil para datos de una sesión de navegaciónsessionStorage.setItem('pasoFormulario', '3');⚠️ Límites y consideraciones
Section titled “⚠️ Límites y consideraciones”Límite de ~5MB
Section titled “Límite de ~5MB”El límite varía ligeramente entre navegadores (5-10MB). Superarlo lanza una excepción QuotaExceededError:
function esSeguroGuardar(clave, valor) { try { const test = JSON.stringify(valor); localStorage.setItem('__test__', test); localStorage.removeItem('__test__'); return true; } catch (e) { if (e.name === 'QuotaExceededError' || e.code === 22) { console.warn('Storage lleno'); return false; } throw e; }}No es seguro para datos sensibles
Section titled “No es seguro para datos sensibles”- Los datos están en texto plano en el disco del usuario.
- Cualquier script en la misma página puede acceder a
localStorage. - No uses
localStoragepara passwords, tokens de autenticación o datos sensibles.
Síncrono y bloqueante
Section titled “Síncrono y bloqueante”Las operaciones de localStorage son síncronas y bloquean el hilo principal. Para grandes volúmenes, considera IndexedDB.
💻 Caso de uso: preferencias de usuario
Section titled “💻 Caso de uso: preferencias de usuario”// Valores por defectoconst DEFAULTS = { tema: 'claro', idioma: 'es', fontSize: 16};
function cargarPreferencias() { const guardadas = localStorage.getItem('preferencias'); return guardadas ? { ...DEFAULTS, ...JSON.parse(guardadas) } : DEFAULTS;}
function guardarPreferencias(prefs) { const actuales = cargarPreferencias(); const nuevas = { ...actuales, ...prefs }; localStorage.setItem('preferencias', JSON.stringify(nuevas));}
// UsoguardarPreferencias({ tema: 'oscuro' });const prefs = cargarPreferencias();console.log(prefs.tema); // 'oscuro'console.log(prefs.idioma); // 'es' (default)📝 localStorage en Node.js
Section titled “📝 localStorage en Node.js”No existe de forma nativa. Para tests o SSR se usa un polyfill o un mock:
// Mock simple para testingclass MockStorage { constructor() { this.store = {}; } getItem(k) { return this.store[k] ?? null; } setItem(k, v) { this.store[k] = String(v); } removeItem(k) { delete this.store[k]; } clear() { this.store = {}; } get length() { return Object.keys(this.store).length; }}
global.localStorage = new MockStorage();🎯 Regla de oro: usa
localStoragepara preferencias de usuario y datos no sensibles que deben persistir entre sesiones. UsasessionStoragepara datos temporales de una sesión. Nunca guardes contraseñas ni tokens de autenticación.