Introduction
Nous voilà dans un article faisant partie d’une série de court articles sur des astuces de programmation. Cet article fait référence à la décomposition (destructuring) en javascript. La décomposition permet d’extraire des données d’un objet ou d’un tableau à l’aide d’une syntaxe introduite avec ES6. Lorsque une nouvelle syntaxe permet de gagner en lisibilité on parle de sucre syntaxique.
1. La décomposition depuis un objet
Pour comprendre la décomposition d’un objet, utilisons cet exemple de code :
const simpleUser = {
firstName: "Thomas",
lastName: "GICQUEL",
job: "développeur"
};
const complexUser = {
info: {
firstName: "Thomas",
lastName: "GICQUEL",
},
pro: {
job: "développeur",
company: 'C2S Bouygues',
techs: ['C#', '.Net', '...']
}
};
1.1 Affectation
a. Simple
Nous allons voir comment affecter des propriétés d’un objet à des variables
// A éviter ❌
console.log('Bonjour, ', simpleUser.firstName);
// Bonjour, Thomas
// Recommandé ✔️
const { firstName } = simpleUser;
console.log('Bonjour, ', firstName);
// Bonjour, Thomas
Note : Cela fonctionne car
firstName
est une propriété de l’objetsimpleUser
.
b. Propriété imbriquée
Passons maintenant aux propriétés imbriquées (nested), nous venons de voir que l’action de décomposer l’objet simpleUser
permet de gagner en lisibilité.
Qu’en est-il lorsque nous l’appliquons pour un objet plus complexe ?
Imaginez que nous souhaitions afficher l’intégralité des propriétés de complexUser
.
// A éviter ❌
console.log(`Bonjour ${complexUser.info.firstName} ${complexUser.info.lastName},
Je vois que vous travaillez à ${complexUser.pro.company} en tant que ${complexUser.pro.job} sur les technologies ${complexUser.pro.techs.join(' ')}.
J'ai actuellement une superbe opportunité pour vous 😅
`);
// Bonjour Thomas GICQUEL,
// Je vois que vous travaillez à C2S Bouygues en tant que développeur sur les technologies C# .Net ....
// J'ai actuellement une superbe opportunité pour vous 😅
Dans cet exemple l’accès à une propriété se fait sur plusieurs niveaux complexUser.info.firstName
à chaque fois que l’on souhaite accéder à une propriété il est donc nécessaire de répéter ce radical.
En utilisant la décomposition, nous pouvons réduire drastiquement le taille du code.
// Recommandé ✔️
const { info: {firstName, lastName}, pro: { company, job, techs } } = complexUser;
console.log(`Bonjour ${firstName} ${lastName},
Je vois que vous travaillez à ${company} en tant que ${job} sur les technologies ${techs.join(' ')}.
J'ai actuellement une superbe opportunité pour vous 😅
`);
// Bonjour Thomas GICQUEL,
// Je vois que vous travaillez à C2S Bouygues en tant que développeur sur les technologies C# .Net ....
// J'ai actuellement une superbe opportunité pour vous 😅
c. Alias
Dans certain cas, il est peut être intéressant de renommer la propriété lors de la décomposition, cela se fait de cette façon :
const { firstName: prenom } = simpleUser;
console.log('Bonjour, ', prenom);
// Bonjour, Thomas
Note : D’ailleurs si dans votre éditeur de code (Visual Code ou autre) vous faites
F2
dans le but de renommer une propriété, il est possible qu’il utilise cette syntaxe à chaque endroit où vous utilisez la décomposition.
d. Valeur par défaut
Si une propriété n’existe pas, il peut être intéressant de lui affecter une valeur par défaut, il est tout à fait possible de le faire lors de la décomposition d’un objet :
const { firstName, techs = ['C#', 'JS', '...'] } = simpleUser;
console.log(techs);
/// (3) ['C#', 'JS', '...']
Note : Si la propriété
techs
n’existe pas dans l’objetcomplexUser
ou que cette propriété est àundefined
elle sera initialisée avec les valeurs par défaut['C#', 'JS', '...']
.
1.2 Affectation avec reste
Reprenons l’exemple de notre objet complexUser
.
Si seulement une partie des propriétés nous intéresse et que nous souhaitons stocker le reste dans un autre objet, il est possible de le faire via l’opérateur spread, dont le symbole est ...
const { info: {firstName, lastName}, ...otherProps} = complexUser;
console.log('rest ->' , otherProps);
/// rest -> { pro: { company: "C2S Bouygues", job: "développeur", techs: (3) ['C#', '.Net', '...'] } }
Dans l’objet otherProps
il reste l’intégralité des propriétés de complexUser
a l’exception de firstName
et lastName
.
À noter que nous pouvons appeler comme nous le voulons la propriété après les ...
.
Note : Cette syntaxe est très utilisée lorsque l’on souhaite passer un objet dont on ne connaît pas les propriétés. Par exemple lorsqu’on développe une application en React et que l’on souhaite passer du style à notre composant enfant. Le composant enfant peut recevoir du style dans un objet, ce composant souhaite récupérer la
width
et laheight
pour faire des calculs et appliquer l’intégralité des autres paramètres reçus. Dans ce cas nous pouvons faire ceci
const { width, height, ...rest} = objCss;
// on utilise la height & la width pour faire des chose
return (
<Component width={width} height={height} ...rest/>
)
2. La décomposition depuis un tableau
2.1 Affectation
Nous allons voir comment affecter des éléments du tableau à des variables.
// A éviter ❌
const array = ['c2s', 'bouygues', 'recrute'];
const item2 = array[1];
console.log('item2 -> ', item2);
// item2 -> recrute
// Recommandé ✔️
const array = ['c2s', 'bouygues', 'recrute'];
const [item1, item2, item3] = array;
console.log('item2 -> ', item2);
// item2 -> recrute
Comme on peut le voir item1
prends le contenu du tableau array
à l’index 0
et ainsi de suite.
Note : Il est préférable d’utiliser cette syntaxe plutôt que d’essayer d’accéder au tableau via son index. Il existe une autre syntaxe permettant de cibler directement l’élément à la position 1 sans avoir besoin de déclarer l’élément à la position 0.
const array = ['c2s', 'bouygues', 'recrute'];
const [, item2] = array;
console.log('item2 -> ', item2);
// item2 -> recrute
Note : Ici la virgule permet de définir le nombre d’element que l’on souhaite passer. Bien évidemment, si l’on essaye d’accéder à un élément inexistant, notre constante sera initialisée avec
undefined
.
2.2 Affectation avec reste
Nous allons voir comment affecter une partie des éléments du tableau dans des variables de la même façon que pour l’affectation tout en copiant le reste dans une variable unique.
const array = ['c2s', 'bouygues', 'recrute', 'des', 'développeurs'];
const [item1, item2, ...other] = array;
console.log('item1 -> ', item1);
// item1 -> c2s
console.log(other);
// ['recrute', 'des', 'développeurs']
console.log(item1, other.join(' '))
// c2s recrute des développeurs
Cette technique est très utile, notamment lorsqu’on ne connaît pas la taille du tableau et que l’on souhaite utiliser l’intégralité des éléments.
2.3 Permutation
Il est aussi possible de permuter le contenu des variables, même si je vous le déconseille pour un soucis de compréhension du code 😁.
let item1 = 'c2s';
let item2 = 'bouygues';
let item3 = 'recrute';
[item1, item2, item3] = [item3, item2, item1];
console.log('item1 -> ', item1);
// item1 -> recrute
console.log('item2 -> ', item2);
// item1 -> bouygues
console.log('item3 -> ', item3);
// item1 -> c2s
Nous pouvons voir que le contenu de item1 et item3 ont permutés
Conclusion
L’arrivé de ES6 en 2015 a permis de simplifier l’écriture en javascript. Il est important pour tout développeur Front ou Full Stack de maîtriser cette manière moderne d’écrire du code Javascript. Cependant nous sommes tous Humain et il peut arriver qu’un oublie surgisse 😉 pour prévenir aux potentiels défauts de mémoire il est essentiel de configurer son linter.
Dans cet article, nous avons traité uniquement de la décomposition des objets et des tableaux apporté par ES6. Ce standard apporte plein d’autres fonctionnalités que nous nous ferons un plaisir de vous faire découvrir sur notre blog.