Adopter les bonnes pratiques

Espace de noms

1. Principe

Lorsque nous développons, nous éviterons toujours d’exposer un trop grand nombre de fonctions ou de variables/constantes dans l’espace de noms global afin d’éviter les conflits de nom. Cela signifie de ne donner l’accès qu’à ce qui est utile et masquer tout le reste. C’est un peu le principe d’une boîte noire avec des entrées et sorties bien définies mais la mécanique interne reste cachée.

C’est d’autant plus important si le code risque d’être utilisé dans d’autres contextes. Le problème vient que nous avons l’habitude d’ajouter des fonctions dans nos fichiers sans prendre en compte la réutilisation. Notre projet devenant plus conséquent, il devient de plus en plus difficile à maintenir. Associer deux codes peut alors provoquer des conflits qui ne sont pas forcément visibles au premier coup d’œil et le résultat d’exécution devient incertain.

Pour limiter les conflits de nom, nous ajouterons un contexte supplémentaire (une sorte de super contexte) qui garantira que nos fonctions et variables/constantes ne pourront être altérées/utilisées accidentellement. Cet espace de noms est une sorte de conteneur de noms. Un nom n’a alors de sens que par rapport à son espace de noms. Invoquer une fonction qui n’est pas dans l’espace de noms attendu devient donc impossible.

Chaque code ayant son espace de noms, il n’y a plus de risque de collisions associé à un code appartenant à un autre espace de noms.

Un espace de noms est une possibilité associée à de nombreux langages. Dans le langage Java, par exemple, le mot-clé package sert à effectuer la déclaration, de même en C# avec namespace. En JavaScript, nous n’avons malheureusement pas de mot-clé pour cet usage mais nous avons d’autres astuces tout aussi puissantes pour l’obtenir.

Ce principe est important pour la qualité de vos programmes. Une fois que l’aurez compris, il deviendra naturel et votre développement s’améliorera d’autant plus.

Plus votre programme est important et plus vous avez besoin d’espaces de noms. C’est la dimension de votre projet...

Module

1. Présentation

Le concept de module découle de la structure précédente. L’idée est de proposer un format universel aux briques de fonctionnalités. Un module représente une partie indépendante de notre code. Par exemple, nous pourrions avoir un module chargé d’un type de calcul ou un module représentant un composant graphique. Un module ne doit pas être confondu avec une fonction ; il est au-dessus de la fonction et masque toutes les fonctions et propriétés utiles pour rendre un service.

Nous avons vu précédemment que la fonction pouvait servir d’espace de noms protégeant de conflits certaines méthodes ou variables/constantes de notre code. Cela a conduit à la conception de notre module :

function monModule { 
   // Définition privée 
   variables ... 
   fonctions ... 
 
   return { 
      // Définition publique 
      propriétés... 
      méthodes... 
   } 
} 

Cette structure peut être employée partout et remplace même vos classes. Nous pourrons également retourner indifféremment un objet unique, un constructeur ou bien une fonction. 

Si par exemple vous voulez obtenir plusieurs instances, dans ce cas, il faut un constructeur qui se chargera de produire les instances à la demande :

function monModule {    
   // Définition privée 
   variables pour toutes les instances... 
   fonctions ... 
 
  // Constructeur intermédiaire pour chaque instance 
  return function() {  
    return...

CommonJS

1. Présentation

Si nous souhaitons rendre un module plus accessible, donc facilement exploitable par tous, il faut se conformer à un standard, d’où l’usage de solutions comme ce que propose CommonJS (http://www.commonjs.org/). CommonJS est né en 2009 sous l’impulsion de Kevin Dangoor avec l’idée de pouvoir normaliser certaines API de JavaScript. Comme nous l’avons vu jusqu’ici, JavaScript offre une grande expressivité dans le codage qui s’avère agréable mais qui cache aussi un véritable problème de normalisation et d’interopérabilité. Cette forme normalisée a ensuite été reprise pour le projet Node.js.

2. exports

Comme nous l’avons vu précédemment, un module avec une fonction anonyme va retourner une valeur, une fonction, une classe, un objet, etc. Dans CommonJS, ce principe a été normalisé par la propriété exports accessible à partir d’un objet module associé à chaque fichier représentant un module. Tout ce qui n’est pas associé à la propriété exports devient caché (comme si c’était à l’intérieur de notre fonction anonyme).

Si nous devons faire le parallèle entre l’usage d’un module par une fonction anonyme et l’usage d’un module CommonJS, nous aurions ceci :

Module par fonction anonyme :

exports =(function()...

Modules ES

1. Présentation

Les modules ES (ou ESM) sont une forme standardisée des modules présents depuis la norme ES6. Ils reposent sur deux principes, un fichier représentant un module. À l’intérieur, la partie visible du module est exportée (par export). L’accès à un module se fait, lui, par le mot-clé import en précisant la référence reçue par le module (ce qui est exporté) et le chemin vers le fichier du module en question.

Les modules ES sont asynchrones, ils n’entraînent donc pas de blocage à l’exécution.

2. export

Le principe est le même que pour les modules CommonJS, par contre l’export est un mot-clé et non une fonction ou une propriété d’un objet. Ce mot-clé export peut être utilisé à plusieurs endroits. Par exemple, devant une fonction, un objet ou une classe. On peut donc avec les modules ES exporter plusieurs choses à la fois. Quand on voudra importer, il faudra juste bien reprendre le même nom que la partie exportée : par exemple, si on exporte une fonction test, il faudra importer une fonction test aussi.

Si nous exportons une fonction calcul, nous pourrons avoir ce module :

// module3.js  
  
function addition(v1,v2) {  
    return v1 + v2;  
}  
   
function division(v1,v2) {  
    return v1 / v2;  
} 
  export function calcul(operateur,v1,v2) {  
    switch( operateur ) {  
       ...

Console

1. Accès

Comme nous l’avons déjà vu dans le premier chapitre, les navigateurs récents disposent tous d’une console JavaScript. Cette console ne sert pas qu’aux messages d’erreurs ; il est possible d’y accéder directement par votre script.

Voici un tableau de rappel des raccourcis-clavier pour accéder à la console selon votre navigateur. Sur Firefox, il est conseillé d’effectuer l’installation de Firebug présent maintenant dans FireFox Developer Edition (https://getfirebug.com/).

Microsoft Edge

[Ctrl][Shift] i ou bien en passant par le sous-menu Outils supplémentaires - Outils de développement

Firefox Developer Edition

[F12]

Chrome

[Ctrl][Shift] J ou [F12]

Safari

[Cmd][Option] I

Opera

[Ctrl][Shift] I ou [F12]

2. log

Pour interagir avec les consoles, un objet prédéfini console est à disposition. Attention car il n’est pas supporté sur les anciens navigateurs. La méthode log autorise un nombre indéterminé d’arguments. Il faut que l’encodage de vos caractères soit bien spécifié avant usage grâce à la balise meta.

Exemple

<!DOCTYPE html> 
<html> 
    <head> 
        <script> 
// Usage simple de la console du navigateur 
for ( let i = 10; i >= 0; i -- ) { 
    console.log( i ); 
} 
 
</script> 
    </head> 
    <body> 
    </body>
</html> 

Voici le résultat sous Firefox Developer Edition après activation et actualisation :

images/03EI05N4.PNG

Sous Chrome :

images/03EI06N4.PNG

Sous Microsoft Edge après actualisation :

images/03EI07N4.PNG

Si vous utilisez plusieurs arguments, ils seront concaténés et séparés par un espace pour former une nouvelle chaîne.

Exemple

console.log( 1, 2, "test" ); 

Ce qui donne dans la console :

1 2 test 

La méthode log supporte également le formatage de type « printf ».

Exemple

console.log( "test %d %s", 10, "ok" ); 

Avec cet affichage dans la console :

test 10 ok 

Les propriétés d’un objet peuvent également être observées. Une variante existe en utilisant la méthode...