Décomposition et déstructuration en Javascript
La décomposition et la déstructuration sont deux termes spécifiques pour exprimer la même chose. La décomposition s’applique aux tableaux et la déstructuration aux objets.
Maintenant que nous avons cerné les différences de nommage, le terme décomposition étant le seul retenu dans les RFCs et autres spécifications d’Ecma International, nous n’utiliserons plus que celui-ci dans le reste de cet article.
La décomposition consiste à "décomposer" les structures complexes (tableau, objet) pour en extraire les valeurs qui nous intéressent. L’intérêt est de rendre ce genre de manipulation plus simple et le code plus lisible.
let [ valeur1, valeur2 ] = tableau
let { valeur1, valeur2 } = objet
La syntaxe est différente s’il s’agit d’un tableau ou d’un objet.
Décomposer des tableaux
Un cas concret de décomposition des tableaux est lorsque nous souhaitons récupérer les valeurs d’un tableau.
let args = ['fruits', 'pomme', 'poire', 'abricot']
let type = args[0]
let firstEl = args[1]
let secondEl = args[2]
let thirdEl = args[3]
Sans décomposition voici comment on récupère des valeurs d’un tableau pour pouvoir les utiliser.
let args = ['fruits', 'pomme', 'poire', 'abricot']
let [type, firstEl, secondEl, thirdEl] = args
La même chose avec la décomposition.
Les deux codes sont similaires, le résultat est le même. Dans les deux cas les variables type
, firstEl
, secondEl
, thirdEl
sont créées.
Si nous nous arrêtons là, cette syntaxe n’a pas trop d’intérêt si ce n’est peut-être nous faire économiser trois lignes. Mais la décomposition vous réserve bien d'autres surprises qui vous feront gagner beaucoup de temps.
Nous ne comparerons pas à chaque fois avec des exemples sans décomposition, mais essayez de réfléchir à comment vous coderiez la même fonctionnalité sans décomposition.
Cas : Si je ne veux récupérer que le type et le second élément.
let args = ['fruits', 'pomme', 'poire', 'abricot']
let [type,, secondEl] = args
Il suffit d’ajouter une virgule entre args[0]
et args[2]
mais sans préciser de nom de variable dans laquelle mettre args[1]
.
Cas : Si args
est vide mes variables type
et secondEl
seront créées, mais auront pour valeur undefined
. Pour pouvoir continuer à travailler avec, il faudrait que je teste mes variables. Mais je peux aussi leur attribuer des valeurs par défaut.
let args = []
let [type = 'legume', firstEl = 'salade'] = args
Comme args
est vide, type
vaudra "légume" et firstEl
vaudra "salade".
Cas : Si je veux récupérer le type de mes éléments dans une variable, mais qu’il est plus pratique pour moi que la liste des éléments soient dans un tableau pour pouvoir boucler dessus.
let args = ['fruits', 'pomme', 'poire', 'abricot']
let [type, ...elements] = args
Ici type
vaudra "fruits" et elements
vaudra ['pomme', 'poire', 'abricot']
.
La syntaxe ici est assez particulière, car elle utilise ce que l’on appelle un paramètre du reste. Si vous souhaitez en savoir plus sur les paramètres du reste, lisez cet article.
On peut aussi utiliser la décomposition pour des cas auxquels on ne pense pas forcément :
Cas : Si je veux intervertir les valeurs de deux variables.
let valA = 'coucou'
let valB = 'byebye'
[valA, valB] = [valB, valA]
Logiquement valA
vaudra "byebye" et valB
vaudra "coucou".
Cas : La décomposition peut-être utilisée pour travailler avec des fonctions qui retournent des tableaux.
let [max, min] = getMaxAndMin([3, 34, 2, 5, 6, 22, 33, 1])
L’intérêt ici est encore la lisibilité du code. Il faudra évidement être sûr de l'ordre des valeurs retournées par la fonction utilisée.
Cas : Il est possible d’utiliser la décomposition en paramètre de fonction.
function firstIsTrue([ first = false ]) {
return first === true
}
firstIsTrue()
prend en paramètre un tableau. Seule la première valeur sera transmise à la fonction et si le tableau est vide first
vaudra false
.
Pour l’utilisateur de la fonction tout est transparent.
Décomposer des objets
La décomposition des objets est relativement la même que celle des tableaux avec quelques spécificités. Nous allons donc passer dessus un peu plus vite pour ne voir que les notions intéressantes.
Cas : Récupération d’une des clés
let objet = {
slug: 'test'
title: 'Ceci est un test'
content: '...'
visible: true
}
let { title } = objet
Exemple de base où on ne veut que le titre. Vous noterez l’utilisation des accolades à la place des crochets lorsqu’il s’agit d’objet.
Cas : Valeur par défaut
let objet = {
slug: 'test'
title: 'Ceci est un test'
content: '...'
visible: true
}
let { visible = false } = objet
On ne veut que la visibilité et qu’elle soit par défaut à false
.
Cas : Utilisation d’un autre nom pour une clé
let objet = {
slug: 'test'
title: 'Ceci est un test'
content: '...'
visible: true
}
let { content: article } = objet
Ici, nous récupérons uniquement la clé content
que nous stockons dans la variable article
.
La vraie syntaxe de la décomposition est celle utilisée dans cet exemple. Dans les autres exemples nous utilisons une astuce de ES2015 qui nous évite d'écrire deux fois la même chose quand c’est possible. Retenez juste que { visible: visible }
est égale à { visible }
.
Cas : Cumul de la valeur par défaut et du changement de nom
let objet = {
slug: 'test'
title: 'Ceci est un test'
content: '...'
visible: true
}
let { visible: isVisible = false } = objet
Nous récupérons la clé visible
que nous stockons dans la variable isVisible
. Cette variable vaudra par défaut false
.
Cas : Utilisation de la décomposition en paramètre de fonction
Il s’agit clairement du cas qui me pousse le plus à utiliser la décomposition. C’est un gain de temps impressionnant.
Vous avez surement déjà écrit des fonctions avec un paramètre options
qui rassemble toutes vos options dans un objet. Pensez au temps que vous avez perdu et au nombre de lignes que vous avez écrit pour tester ce seul paramètre avant même de coder du métier.
function test(id, { maxLength = 10, current = 0 } = {})
Comme pour la décomposition de tableau, le fait de l’utiliser dans les paramètres d’une fonction est totalement transparent pour l’utilisateur, mais pour vous ça change tout.
maxLength
et current
ne seront jamais undefined
, auront toujours une valeur que ce soit celle de l’utilisateur ou la valeur par défaut. Et ça allégera votre code vu que vous ne ferez plus options.maxLength
mais juste maxLength
comme s’il s’agissait d’un simple paramètre comme id
.
Seul les attributs que vous avez déclarés dans la décomposition seront transmit à votre fonction. L’utilisateur peut bien ajouter 15 000 autres attributs à options
ils ne seront pas transmis. Ce qui ajoute un léger niveau de sécurité à votre fonction.
Conclusion
J’espère sincèrement que vous avez été convaincu. La décomposition est, pour moi, une des plus grosses nouveautés de ES2015.
Une fonctionnalité puissante à utiliser sans modération pour rendre votre code plus simple, clair, concis, beau, propre, etc. Et vous savez à quel point j’aime le code propre.
Pour aller plus loin :