Immuabilité en JavaScript : produire une nouvelle valeur plutôt que modifier l'ancienne

L'immuabilité consiste à ne jamais modifier une valeur existante mais à en produire une copie modifiée. Copies, gel et méthodes qui ne mutent pas.
3 min de lecture
Believemy logo

Un tableau modifié à un endroit du code peut changer sous les pieds d'un autre endroit qui le tenait déjà. Le bogue est silencieux, apparaît loin de sa cause, et résiste bien à la relecture.

L'immuabilité coupe court à ce scénario en posant une discipline simple : on ne modifie rien, on produit une nouvelle valeur.


Définition

L'immuabilité est le principe selon lequel une valeur, une fois créée, n'est plus modifiée. Toute évolution passe par la création d'une copie portant le changement. L'ancienne version reste intacte pour ceux qui la détenaient.

JAVASCRIPT
const panier = ["clavier", "souris"];
const avecEcran = [...panier, "écran"];

console.log(panier);    // [ 'clavier', 'souris' ]
console.log(avecEcran); // [ 'clavier', 'souris', 'écran' ]

const profil = { nom: "Ada", ville: "Londres" };
const demenage = { ...profil, ville: "Paris" };

console.log(profil.ville);   // Londres
console.log(demenage.ville); // Paris

Le Spread (...) fait tout le travail : il recopie le contenu dans une structure neuve, et ce qui est écrit après lui remplace ce qui vient d'être copié.


Le geste équivalent, en version immuable

Chaque opération qui modifie sur place a son pendant qui renvoie une copie. Ce tableau à trois colonnes couvre les quatre cas quotidiens.

BesoinVersion qui modifieVersion qui copie
Ajouter en finliste.push(x)[...liste, x]
Retirer un élémentliste.splice(i, 1)liste.filter(...)
Trierliste.sort()liste.toSorted()
Changer un champobj.champ = v{ ...obj, champ: v }


Object.freeze et sa limite

const empêche de réaffecter un nom, pas de modifier ce qu'il contient. Object.freeze() va plus loin, mais s'arrête au premier niveau.

JAVASCRIPT
const config = Object.freeze({ langue: "fr", options: { son: true } });

console.log(Object.isFrozen(config));         // true
console.log(Object.isFrozen(config.options)); // false, le gel ne descend pas

config.options.son = false;
console.log(config.options.son);              // false
Bon à savoir

Écrire config.langue = "en" est ignoré en silence dans un script classique, et lève une TypeError dans un module. Le gel protège donc, mais pas de la même façon partout.


Questions fréquentes

Question

Copier sans arrêt ne coûte-t-il pas cher ?

Une copie superficielle ne duplique que le premier niveau : les valeurs imbriquées sont partagées, pas recréées. Sur des listes de quelques milliers d'éléments, le coût est sans commune mesure avec le temps passé à traquer une Mutation imprévue. Le vrai risque serait la copie profonde systématique, rarement nécessaire.


Question

const rend-il une valeur immuable ?

Non, et c'est la confusion la plus répandue. const interdit de réaffecter le nom, rien de plus. Un tableau déclaré avec const accepte parfaitement push(), parce que la variable pointe toujours vers le même tableau. Voir Référence et valeur pour le détail.


Question

Pourquoi les interfaces modernes y tiennent-elles autant ?

Parce qu'une bibliothèque d'affichage détecte un changement en comparant deux références. Si l'objet a été modifié sur place, l'ancienne et la nouvelle sont identiques et rien ne se met à jour. Notre formation React revient sur ce point dès la première mise à jour d'état, là où la règle devient concrète.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.