140 votes

Modèle de module JavaScript avec exemple

Je ne trouve pas d'exemples accessibles montrant comment deux modules différents (ou plus) sont connectés pour fonctionner ensemble.

J'aimerais donc savoir si quelqu'un a le temps d'écrire un exemple expliquant comment les modules fonctionnent ensemble.

0 votes

Tout cela a changé au cours des quatre dernières années, mais grâce à une surmodération zélée, ces informations périmées resteront en place. pour toujours . Voici Page de MDN sur les modules ES6.

265voto

kta Points 4702

Pour aborder le modèle de conception modulaire, il faut d'abord comprendre ces concepts :

Expression de la fonction immédiatement invoquée (IIFE) :

(function() {
      // Your code goes here 
}());

Les fonctions peuvent être utilisées de deux manières. 1. Déclaration de fonction 2. Expression de fonction.

Nous utilisons ici une expression de fonction.

W Si nous ajoutons l'espace de noms au morceau de code ci-dessus, alors

var anoyn = (function() {
}());

Qu'est-ce que la fermeture en JS ?

Cela signifie que si nous déclarons une fonction avec une variable quelconque à l'intérieur d'une autre fonction (en JS, nous pouvons déclarer une fonction à l'intérieur d'une autre fonction !), cette fonction sera toujours prise en compte. Cela signifie que toute variable dans une fonction extérieure sera toujours lue. Elle ne lira pas la variable globale (s'il y en a une) portant le même nom. C'est également l'un des objectifs de l'utilisation d'un modèle de conception modulaire, qui permet d'éviter les conflits de noms.

var scope = "I am global";
function whatismyscope() {
    var scope = "I am just a local";
    function func() {return scope;}
    return func;
}
whatismyscope()()

Nous allons maintenant appliquer les trois concepts mentionnés ci-dessus pour définir notre premier modèle de conception modulaire :

var modularpattern = (function() {
    // your module code goes here
    var sum = 0 ;

    return {
        add:function() {
            sum = sum + 1;
            return sum;
        },
        reset:function() {
            return sum = 0;    
        }  
    }   
}());
alert(modularpattern.add());    // alerts: 1
alert(modularpattern.add());    // alerts: 2
alert(modularpattern.reset());  // alerts: 0

jsfiddle pour le code ci-dessus.

L'objectif est de cacher l'accessibilité variable au monde extérieur.

J'espère que cela vous aidera. Je vous souhaite bonne chance.

0 votes

Serait-il préférable de nommer l'iife ? à des fins sémantiques et pour un meilleur suivi de la pile ? cela changerait-il quoi que ce soit au code ?

2 votes

Votre premier exemple (function() { /* Your code goes here */}()); est en fait une IIFE (Immediately Invoking Function Expression), ok elle est anonyme car elle n'a pas de nom, vous pouvez donc l'appeler une IIAFE (Immediately Invoking Anonymous Function Expression) voir plus d'informations sur les IIFE sur stackoverflow.com/questions/2421911/

0 votes

Pourquoi l'instruction return a-t-elle été utilisée ? si nous omettons return {}, les fonctions add et reset seront publiques et je suppose qu'elles peuvent accéder à la variable locale sum ? ai-je raison ?

40voto

Code Novitiate Points 746

Je recommande vivement à tous ceux qui s'intéressent à ce sujet de lire le livre gratuit d'Addy Osmani :

"Apprendre les modèles de conception JavaScript".

http://addyosmani.com/resources/essentialjsdesignpatterns/book/

Ce livre m'a énormément aidé lorsque j'ai commencé à écrire un JavaScript plus facile à maintenir et je l'utilise toujours comme référence. Jetez un coup d'œil à ses différentes implémentations du modèle de module, il les explique vraiment bien.

0 votes

Je vous recommande également de lire mon article sur le "Definitive Module Pattern", qui n'est pas abordé dans le livre d'Addy Osmani : github.com/tfmontague/definitive-module-pattern

1 votes

Quelle est la comparaison avec "JavaScript Patterns" de Stoyan Stefanov ?

4 votes

Le livre de Stoyan est beaucoup plus complet. Il ne couvre pas seulement les modèles de haut niveau, mais parle aussi plus en profondeur d'autres meilleures pratiques JS.

19voto

Jonny Leeds Points 741

J'ai pensé développer la réponse ci-dessus en parlant de la manière dont les modules s'intègrent dans une application. J'avais lu cela dans le livre de Doug Crockford, mais étant novice en javascript, cela restait un peu mystérieux.

Je viens d'une formation en c# et j'ai donc ajouté une terminologie que je trouve utile dans ce domaine.

Html

Vous obtiendrez une sorte de fichier html de premier niveau. Il est utile de le considérer comme le fichier de votre projet. Chaque fichier javascript que vous ajoutez au projet doit aller dans ce fichier, malheureusement vous n'avez pas de support d'outil pour cela (j'utilise IDEA).

Vous devez ajouter des fichiers au projet avec des balises script comme ceci :

        <script type="text/javascript" src="app/native/MasterFile.js" /></script>
        <script type="text/javascript" src="app/native/SomeComponent.js" /></script>

Il semble que le fait de réduire les balises fasse échouer les choses - alors que cela ressemble à xml, il s'agit en fait de quelque chose avec des règles plus folles !

Fichier de l'espace de noms

MasterFile.js

myAppNamespace = {};

c'est tout. Il s'agit simplement d'ajouter une seule variable globale pour le reste de notre code. Vous pouvez également déclarer des espaces de noms imbriqués ici (ou dans leurs propres fichiers).

Module(s)

SomeComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

    var incrementCount = function () {
        privateState += 1;
    };

    return function (message) {
        incrementCount();
        //TODO something with the message! 
    }
})();

Ce que nous faisons ici, c'est assigner une fonction de compteur de messages à une variable de notre application. Il s'agit d'une fonction qui renvoie une fonction que nous exécuter immédiatement .

Concepts

Je pense qu'il est utile de considérer la ligne supérieure de SomeComponent comme l'espace de noms dans lequel vous déclarez quelque chose. La seule réserve est que tous vos espaces de noms doivent d'abord apparaître dans un autre fichier - ce ne sont que des objets enracinés par notre variable d'application.

Je n'ai fait que des pas mineurs avec cela pour le moment (je refais du javascript normal hors d'une application extjs pour pouvoir la tester) mais cela semble assez sympa car on peut définir de petites unités fonctionnelles tout en évitant le bourbier de 'ceci' .

Vous pouvez également utiliser ce style pour définir des constructeurs en renvoyant une fonction qui renvoie un objet avec une collection de fonctions et en ne l'appelant pas immédiatement.

6voto

Dmitry Sheiko Points 101

Ici https://toddmotto.com/mastering-the-module-pattern vous trouverez une explication détaillée du modèle. J'ajouterais que la deuxième chose à propos du JavaScript modulaire est la façon de structurer votre code dans plusieurs fichiers. Beaucoup de gens peuvent vous conseiller d'utiliser AMD, mais je peux dire par expérience que vous finirez par avoir des pages lentes à cause des nombreuses requêtes HTTP. La solution consiste à précompiler vos modules JavaScript (un par fichier) dans un seul fichier en suivant la norme CommonJS. Jetez un coup d'œil aux exemples ici http://dsheiko.github.io/cjsc/

0 votes

Toutes les implémentations AMD proposent également une précompilation dans un fichier unique.

1 votes

C'est exact, mais le fichier optimisé qui en résulte nécessite la bibliothèque du chargeur (je viens de le revérifier avec r.js v2.1.14), qui est généralement assez lourde. Dès que nous avons compilé du code, nous n'avons pas besoin de résoudre les dépendances chargées de manière asynchrone, nous n'avons pas besoin de cette bibliothèque. Considérez simplement : nous enveloppons les modules dans AMD, ce qui signifie un chargement asynchrone, puis nous les compilons dans un seul fichier (plus de chargement séparé), mais nous chargeons la bibliothèque entière pour les traiter (ce qui est redondant maintenant). Cela ne me semble pas être une méthode optimale. Pourquoi AMD si nous ne chargeons pas de manière asynchrone ?

0 votes

Almond.js fournit un chargeur plus léger pour le code de production fini que RequireJS, mais comparativement, l'avantage en termes de performances de ne pas faire une seule requête http dépasse de loin le coût de l'ajout du code du chargeur au module, donc même si c'est moins optimal, c'est à une échelle beaucoup plus petite. La question, à mon avis, devrait être inversée : pourquoi supposer un synchronisme alors que le navigateur ne l'est pas ? Je suis en fait d'avis que RequireJS et CommonJS devraient avoir une implémentation de promesse intégrée.

-3voto

Roman Points 1196

Vous pouvez trouver le modèle de module JavaScript ici http://www.sga.su/module-pattern-javascript/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X