localStorage et sessionStorage en JavaScript
Le localStorage est un espace de stockage intégré au navigateur qui permet de conserver des données directement sur la machine de l’utilisateur, sans base de données ni serveur. Préférences d’affichage, panier d’achat, thème sombre, brouillon de formulaire : autant de données que l’on garde côté client grâce à cette API simple. Avec son cousin sessionStorage, elle forme l’API Web Storage. Ce guide couvre chaque méthode, le stockage d’objets complexes, les différences entre les deux stockages, et surtout leurs limites qu’il faut connaître avant de s’en servir.
À quoi sert le localStorage
localStorage stocke des paires clé / valeur de type texte, persistantes : les données survivent à la fermeture de l’onglet, du navigateur, et même au redémarrage de l’ordinateur. Elles restent jusqu’à ce que le code les efface ou que l’utilisateur vide les données de navigation. C’est un objet global accessible partout dans votre JavaScript, propre à chaque domaine (origine).
Les quatre méthodes de base
Toute l’API tient en quatre méthodes plus une propriété. Commençons par écrire et lire une valeur.
// Écrire une valeur
localStorage.setItem("theme", "sombre");
// Lire une valeur
const theme = localStorage.getItem("theme");
console.log(theme); // "sombre"
// Lire une clé qui n'existe pas renvoie null
console.log(localStorage.getItem("inconnu")); // null
Ce point est important : getItem renvoie null (et non undefined) quand la clé n’existe pas. On teste donc souvent la valeur avant de l’utiliser.
Pour supprimer, deux méthodes selon que l’on vise une clé ou tout l’espace.
// Supprimer une seule clé
localStorage.removeItem("theme");
// Tout effacer d'un coup
localStorage.clear();
// Connaître le nombre de clés stockées
console.log(localStorage.length);
Parcourir toutes les clés
On peut lister l’ensemble des données stockées avec la méthode key(index) ou, plus simplement, Object.keys.
// Avec key(index)
for (let i = 0; i < localStorage.length; i++) {
const cle = localStorage.key(i);
console.log(cle, "→", localStorage.getItem(cle));
}
// Plus moderne
Object.keys(localStorage).forEach(cle => {
console.log(cle, "→", localStorage.getItem(cle));
});
Le point clé : tout est stocké en texte
C’est le piège numéro un du localStorage. Il ne stocke que des chaînes de caractères. Si vous y mettez un nombre, vous le récupérez sous forme de texte ; si vous y mettez un objet, il est converti en "[object Object]", illisible.
localStorage.setItem("age", 30);
const age = localStorage.getItem("age");
console.log(typeof age); // "string" (pas "number") !
console.log(age * 2); // 60 tout de même (coercition), mais restez prudent
localStorage.setItem("user", { nom: "Léa" });
console.log(localStorage.getItem("user")); // "[object Object]" — perdu !
Stocker des objets et des tableaux avec JSON
La solution est de sérialiser vos données en JSON avant de les stocker, et de les désérialiser à la lecture. JSON.stringify transforme un objet en texte, JSON.parse fait l’inverse.
const utilisateur = {
nom: "Léa",
age: 30,
preferences: { theme: "sombre", langue: "fr" },
};
// Écriture : objet → texte JSON
localStorage.setItem("user", JSON.stringify(utilisateur));
// Lecture : texte JSON → objet
const recupere = JSON.parse(localStorage.getItem("user"));
console.log(recupere.preferences.theme); // "sombre"
Cela fonctionne pour les tableaux comme pour les objets imbriqués. Un utilitaire réutilisable évite de répéter le couple stringify/parse partout dans le code.
const storage = {
set(cle, valeur) {
localStorage.setItem(cle, JSON.stringify(valeur));
},
get(cle, defaut = null) {
const brut = localStorage.getItem(cle);
if (brut === null) return defaut;
try {
return JSON.parse(brut);
} catch {
return defaut; // valeur corrompue ou non-JSON
}
},
};
storage.set("panier", [{ id: 1, qte: 2 }]);
const panier = storage.get("panier", []);
Le bloc try/catch est une précaution utile : si une valeur a été corrompue ou écrite hors JSON, JSON.parse lève une erreur qu’on intercepte pour renvoyer une valeur par défaut.
localStorage vs sessionStorage
sessionStorage possède exactement la même API (setItem, getItem, removeItem, clear), mais une durée de vie différente. C’est la seule chose à retenir pour choisir entre les deux.
// Persistant : survit à la fermeture du navigateur
localStorage.setItem("langue", "fr");
// Temporaire : effacé à la fermeture de l'onglet
sessionStorage.setItem("etapeFormulaire", "3");
Les différences essentielles :
- Durée :
localStoragepersiste indéfiniment ;sessionStoragedisparaît à la fermeture de l’onglet. - Portée :
sessionStorageest propre à un onglet — deux onglets du même site ont chacun le leur.localStorageest partagé entre tous les onglets d’un même domaine. - Cas d’usage : préférences durables (thème, langue) →
localStorage; données temporaires liées à une visite (progression d’un formulaire multi-étapes) →sessionStorage.
L’événement storage : synchroniser les onglets
Quand localStorage change dans un onglet, les autres onglets du même site en sont notifiés par l’événement storage. Attention : l’onglet qui a fait la modification ne le reçoit pas, seulement les autres.
window.addEventListener("storage", (event) => {
console.log("Clé modifiée :", event.key);
console.log("Ancienne valeur :", event.oldValue);
console.log("Nouvelle valeur :", event.newValue);
if (event.key === "theme") {
appliquerTheme(event.newValue);
}
});
C’est très pratique pour synchroniser une interface : si l’utilisateur change de thème dans un onglet, tous les autres se mettent à jour instantanément. La gestion de ces événements repose sur addEventListener ; notre guide sur les événements en JavaScript détaille ce mécanisme.
Les limites à connaître
Le localStorage est pratique mais loin d’être une base de données. Plusieurs contraintes fortes conditionnent son usage.
Taille limitée
Chaque domaine dispose d’environ 5 Mo (la valeur varie selon les navigateurs). Dépasser ce quota lève une exception QuotaExceededError. Enveloppez les écritures volumineuses dans un try/catch.
try {
localStorage.setItem("gros", JSON.stringify(donneesVolumineuses));
} catch (e) {
console.error("Quota de stockage dépassé", e);
}
Opérations synchrones et bloquantes
Toutes les opérations sont synchrones : lire ou écrire beaucoup de données bloque le thread principal et peut figer l’interface. Pour de gros volumes ou des données structurées, tournez-vous vers IndexedDB, conçu pour cela.
Sécurité : jamais de données sensibles
C’est le point le plus important. Le localStorage est accessible par n’importe quel JavaScript de la page, ce qui l’expose aux attaques XSS. N’y stockez jamais de mot de passe, de numéro de carte, ni de jeton d’authentification sensible. Ces informations exigent des mécanismes plus sûrs (cookies HttpOnly, gérés côté serveur).
localStorage vs cookies
On confond souvent les deux, mais ils répondent à des besoins différents.
- Envoi au serveur : les cookies sont automatiquement joints à chaque requête HTTP vers le domaine ; le localStorage reste purement côté client et n’est jamais transmis.
- Capacité : localStorage offre ~5 Mo contre ~4 Ko pour un cookie.
- Usage : les cookies servent surtout à l’authentification et aux sessions serveur ; le localStorage aux préférences et données d’interface.
En résumé : préférences et état d’interface → localStorage ; session et authentification gérées par le serveur → cookies.
À retenir
localStorage stocke des paires clé/valeur en texte, de façon persistante et propre à chaque domaine, via quatre méthodes : setItem, getItem, removeItem et clear. Pour y placer des objets ou des tableaux, sérialisez-les avec JSON.stringify et relisez-les avec JSON.parse. Choisissez sessionStorage quand la donnée ne doit vivre que le temps de l’onglet. Gardez en tête les trois limites : ~5 Mo d’espace, opérations synchrones, et surtout aucune donnée sensible — le localStorage n’est pas fait pour la sécurité.