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 :
Sous Chrome :
Sous Microsoft Edge après actualisation :
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...