header

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’objet simpleUser.

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’objet complexUser 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 la height 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.