Avoir des variables immuables permet d’éviter certains problèmes pénibles en programmation. C’est un des aspects de la programmation fonctionnelle. Donc, si vous voulez faire de la programmation fonctionnelle en JavaScript, cet article vous montre déjà comment avoir des variables immuables pour les types complexes que sont les tableaux de valeurs.


Partager l’article Geler les tableaux en JavaScript sur les réseaux sociaux


Déclaration de variables en JavaScript

JavaScript permet de déclarer les variables selon 3 méthodes différentes :

  • var myVariable;
  • let myVariable;
  • const myVariable;

L’utilisation de var est fortement déconseillée maintenant. Préférez l’utilisation de let pour une variable qui pourra être amenée à être modifiée/écrasée et const pour une variable ne devant pas changer.

Et non, l’utilisation de const seul ne suffit pas pour des tableaux de données. Sinon ce serait trop simple.

Pour avoir vraiment un tableau gelé, il faut utiliser également Object.freeze().

L’exemple

Nous allons nous appuyer sur ces quatres déclarations de variables d’un même tableau comportant 3 éléments via les mots-clés let ou const, avec ou sans l’appel de Object.freeze() :

let foo = ['a', 'b', 'c'];
const foo = ['a', 'b', 'c'];
let foo = Object.freeze(['a', 'b', 'c']);
const foo = Object.freeze(['a', 'b', 'c']);

Le code exécuté après chaque déclaration

Le code va tenter :

  • de réaffecter le premier item du tableau avec une nouvelle valeur,
  • d’ajouter une nouvelle valeur à la fin du taleau,
  • de remplacer complètement le tableau par un autre.

Via des console.table() et des try … catch(), nous allons observer ce qui se passe…

Voici le code en question :

try {
	foo[0] = 'd';
} catch(e) {
	console.log('Fail assigning "d" value on index 0.');
}

try {
	foo.push('e');
} catch (e) {
	console.log('Fail pushing new "e" value.');
}

console.table(foo);

try {
	foo = ['r', 'e', 's', 'e', 't'];
} catch (e) {
	console.log('Fail reassigning variable using full array.');
}

console.table(foo);

Et maintenant, testons ça !

let seul

Sans trop de surprise, un simple let permet de tout faire sans erreur, pas d’exception levée, et les modifications demandées se sont réalisées.

'd'
4
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'd'   |
|    1    |  'b'   |
|    2    |  'c'   |
|    3    |  'e'   |
+---------+--------+

[ 'r', 'e', 's', 'e', 't' ]
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'r'   |
|    1    |  'e'   |
|    2    |  's'   |
|    3    |  'e'   |
|    4    |  't'   |
+---------+--------+

const seul

Avec const, comme pour let, lajout et la modification d’item au sein du tableau est possible.

Par contre, l’affection d’une nouvelle variable à la place du tableau échoue.

'd'
4
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'd'   |
|    1    |  'b'   |
|    2    |  'c'   |
|    3    |  'e'   |
+---------+--------+
Fail reassigning variable using full array.
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'd'   |
|    1    |  'b'   |
|    2    |  'c'   |
|    3    |  'e'   |
+---------+--------+

Avec const, vous préservez le tableau en temps que tel, mais pas son contenu.

let + Object.freeze

Cette fois, il est impossible de modifier ou d’ajouter un item au tableau.

En revanche, il est possible de subtituer le tableau d’origine par un autre…

Ce n’est donc toujours pas une variable 100% immuable.

'd'
Fail pushing new "e" value.
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'a'   |
|    1    |  'b'   |
|    2    |  'c'   |
+---------+--------+
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'r'   |
|    1    |  'e'   |
|    2    |  's'   |
|    3    |  'e'   |
|    4    |  't'   |
+---------+--------+

Notez que le forçage de valeur pour l’index 0 ne soulève aucune erreur et que la valeur n’est pas écrasée, alors que la tentative d’ajout se solde par la levée d’une exception.

const + Object.freeze

Cette fois, l’utilisation conjointe de const et de Object.freeze() ne permet aucune modification :

  • impossible d’jouter un item
  • impossible de modifier un item
  • impossible de changer la variable dans son ensemble.

Nous avons donc un vrai objet immuable !

'd'
Fail pushing new "e" value.
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'a'   |
|    1    |  'b'   |
|    2    |  'c'   |
+---------+--------+
Fail reassigning variable using full array.
+---------+--------+
| (index) | Values |
+---------+--------+
|    0    |  'a'   |
|    1    |  'b'   |
|    2    |  'c'   |
+---------+--------+

Récapitulons

L’utilisation de let, const et Object.freeze() donne un gradient de modifications possibles qui se résume bien dans le tableau suivant :

Déclaration Changement item(s) Changement total
let Oui Oui
const Oui Non
let + Object.freeze() Non Oui
const + Object.freeze() Non Non

En fonction de l’usage que vous en aurez, tel ou tel gradient peut mieux convenir.

Le plus clair étant celui qui ne permet pas de modification, avec const et Object.freeze().

Note : Bien que ne parlant que de tableaux, ces résultats sont aussi vrai pour des objets en JavaScript.

Photo de Scott Osborn sur Unsplash