Le concept de modules vient du paradigme de la programmation modulaire. Ce paradigme propose que le logiciel soit composé de composants séparés et interchangeables appelés "modules" en décomposant les fonctions du programme en fichiers autonomes qui peuvent fonctionner séparément ou couplés dans un application.

Un module est un fichier autonome qui encapsule du code pour implémenter certaines fonctionnalités et promouvoir la réutilisation et l'organisation.

Ici, vous couvrirez les systèmes de modules utilisés dans les applications JavaScript, y compris le modèle de module, le système de modules CommonJS utilisé dans la plupart des applications Node.js et le système de modules ES6.

Le modèle de module

Avant l'introduction des modules JavaScript natifs, le modèle de conception de module était utilisé comme un système de modules pour étendre les variables et les fonctions à un seul fichier.

Cela a été implémenté à l'aide d'expressions de fonction immédiatement appelées, communément appelées IIFE. Un IIFE est une fonction non réutilisable qui s'exécute dès sa création.

Voici la structure de base d'un IIFE :

(fonction () {
// code ici
})();

(() => {
// code ici
})();

(asynchrone () => {
// code ici
})();

Le bloc de code ci-dessus décrit les IIFE utilisés dans trois contextes différents.

Les IIFE ont été utilisés parce que les variables déclarées à l'intérieur d'une fonction sont étendues à la fonction, ce qui les rend uniquement accessible à l'intérieur de la fonction, et parce que les fonctions vous permettent de renvoyer des données (les rendant publiques accessible).

Par exemple:

constante truc = (fonction () {
constante sayName = (nom) => {
console.enregistrer("Hé, je m'appelle ${nom}`);
};
//Exposer les variables
retour {
callSayName: (nom) => sayName (nom),
};
})();
//Accéder aux méthodes exposées
foo.callSayName("Bar");

Le bloc de code ci-dessus est un exemple de la façon dont les modules ont été créés avant l'introduction des modules JavaScript natifs.

Le bloc de code ci-dessus contient un IIFE. L'IIFE contient une fonction qu'il rend accessible en la retournant. Toutes les variables déclarées dans l'IIFE sont protégées de la portée globale. Ainsi, la méthode (direNom) n'est accessible que par la fonction publique, appelDitesNom.

Notez que l'IIFE est enregistré dans une variable, fou. En effet, sans variable pointant vers son emplacement en mémoire, les variables seront inaccessibles après l'exécution du script. Ce modèle est possible grâce à Fermetures JavaScript.

Le système de modules CommonJS

Le système de module CommonJS est un format de module défini par le groupe CommonJS pour résoudre les problèmes de portée JavaScript en exécutant chaque module dans son espace de noms.

Le système de modules CommonJS fonctionne en forçant les modules à exporter explicitement les variables qu'ils souhaitent exposer à d'autres modules.

Ce système de modules a été créé pour JavaScript côté serveur (Node.js) et, en tant que tel, n'est pas pris en charge par défaut dans les navigateurs.

Pour implémenter des modules CommonJS dans votre projet, vous devez d'abord initialiser NPM dans votre application en exécutant :

npm init -y

Les variables exportées suivant le système de modules CommonJS peuvent être importées comme suit :

//randomModule.js
//paquet installé
constante installImport = exiger("nom du paquet");
//module local
constante importationlocale = exiger("/path-to-module");

Les modules sont importés dans CommonJS en utilisant le exiger instruction, qui lit un fichier JavaScript, exécute le fichier lu et renvoie la exportations objet. Le exportations L'objet contient toutes les exportations disponibles dans le module.

Vous pouvez exporter une variable suivant le système de modules CommonJS en utilisant soit des exportations nommées, soit des exportations par défaut.

Exportations nommées

Les exportations nommées sont des exportations identifiées par les noms qui leur ont été attribués. Les exportations nommées permettent plusieurs exportations par module, contrairement aux exportations par défaut.

Par exemple:

//main.js
exports.myExport = fonction () {
console.log("Ceci est un exemple de un nommé exporter");
};
exports.anotherExport = fonction () {
console.log("Ceci est un autre exemple de un nommé exporter");
};

Dans le bloc de code ci-dessus, vous exportez deux fonctions nommées (monexportation et un autreExporter) en les attachant au exportations objet.

De même, vous pouvez exporter les fonctions comme suit :

constante monExport = fonction () {
console.log("Ceci est un exemple de un nommé exporter");
};
constante une autreExportation = fonction () {
console.log("Ceci est un autre exemple de un nommé exporter");
};
module.exportations = {
monExport,
une autre exportation,
};

Dans le bloc de code ci-dessus, vous définissez le exportations objet aux fonctions nommées. Vous ne pouvez attribuer que exportations objet à un nouvel objet via la module objet.

Votre code renverrait une erreur si vous tentiez de le faire de cette façon :

//Fausse Route
exportations = {
monExport,
une autre exportation,
};

Il existe deux manières d'importer des exportations nommées :

1. Importez toutes les exportations en tant qu'objet unique et accédez-y séparément à l'aide de la notation pointée.

Par exemple:

//otherModule.js
constante foo = exiger("./principal");
fou.monExportation();
fou.anotherExport();

2. Déstructurer les exportations du exportations objet.

Par exemple:

//otherModule.js
constante { monexportation, une autreexportation } = exiger("./principal");
monExport();
une autreExportation();

Une chose est commune à toutes les méthodes d'importation, elles doivent être importées en utilisant les mêmes noms avec lesquels elles ont été exportées.

Exportations par défaut

Une exportation par défaut est une exportation identifiée par le nom de votre choix. Vous ne pouvez avoir qu'une seule exportation par défaut par module.

Par exemple:

//main.js
classeFoo{
bar() {
console.log("Ceci est un exemple de un défautexporter");
}
}
module.exportations = Foo ;

Dans le bloc de code ci-dessus, vous exportez une classe (Foo) en réaffectant le exportations s'y opposer.

L'importation d'exportations par défaut est similaire à l'importation d'exportations nommées, sauf que vous pouvez utiliser le nom de votre choix pour les importer.

Par exemple:

//otherModule.js
constante Barre = exiger("./principal");
constante objet = nouveau Bar();
objet.bar();

Dans le bloc de code ci-dessus, l'exportation par défaut était nommée Bar, bien que vous puissiez utiliser le nom de votre choix.

Le système de modules ES6

Le système de modules ECMAScript Harmony, communément appelé modules ES6, est le système de modules JavaScript officiel.

Les modules ES6 sont pris en charge par les navigateurs et les serveurs, bien que vous ayez besoin d'un peu de configuration avant de les utiliser.

Dans les navigateurs, vous devez spécifier le taper comme module dans la balise d'importation de script.

Ainsi:

//index.html
<script src="./app.js" taper="module"></script>

Dans Node.js, vous devez définir taper pour module dans ton package.json déposer.

Ainsi:

//package.json
"taper":"module"

Vous pouvez également exporter des variables à l'aide du système de modules ES6 en utilisant des exportations nommées ou des exportations par défaut.

Exportations nommées

Semblables aux importations nommées dans les modules CommonJS, elles sont identifiées par les noms qui leur ont été attribués et permettent plusieurs exportations par module.

Par exemple:

//main.js
exporterconstante monExport = fonction () {
console.log("Ceci est un exemple de un nommé exporter");
};
exporterconstante une autreExportation = fonction () {
console.log("Ceci est un autre exemple de un nommé exporter");
};

Dans le système de module ES6, les exportations nommées sont exportées en préfixant la variable avec le exporter mot-clé.

Les exportations nommées peuvent être importées dans un autre module dans ES6 de la même manière que CommonJS :

  • Déstructurer les exportations requises du exportations objet.
  • Importer toutes les exportations en tant qu'objet unique et y accéder séparément à l'aide de la notation par points.

Voici un exemple de déstructuration :

//otherModule.js
importer { monexportation, une autreexportation } depuis "./main.js" ;
monExport()
une autreExportation()

Voici un exemple d'importation de l'objet entier :

importer * comme fou depuis './main.js'
fou.monExportation()
fou.anotherExport()

Dans le bloc de code ci-dessus, l'astérisque (*) signifie "tous". Le comme mot-clé attribue le exportations objet à la chaîne qui le suit, dans ce cas, fou.

Exportations par défaut

Semblables aux exportations par défaut dans CommonJS, elles sont identifiées par le nom de votre choix et vous ne pouvez avoir qu'une seule exportation par défaut par module.

Par exemple:

//main.js
classeFoo{
bar() {
console.log("Ceci est un exemple de un défautexporter");
}
}
exporterdéfaut Fou ;

Les exports par défaut sont créés en ajoutant le défaut mot-clé après le exporter mot-clé, suivi du nom de l'exportation.

L'importation d'exportations par défaut est similaire à l'importation d'exportations nommées, sauf que vous pouvez utiliser le nom de votre choix pour les importer.

Par exemple:

//otherModule.js
importer Bar depuis "./main.js" ;

Exportations mixtes

La norme de module ES6 vous permet d'avoir à la fois des exportations par défaut et des exportations nommées dans un module, contrairement à CommonJS.

Par exemple:

//main.js
exporterconstante monExport = fonction () {
console.log("Ceci est un autre exemple de un nommé exporter");
};
classeFoo{
bar() {
console.log("Ceci est un exemple de un défautexporter");
}
}
exporterdéfaut Fou ;

Importance des modules

Diviser votre code en modules les rend non seulement plus faciles à lire, mais aussi plus réutilisables et maintenables. Les modules en JavaScript rendent également votre code moins sujet aux erreurs, car tous les modules sont exécutés en mode strict par défaut.