JavaScript-Modulmuster mit Beispiel [geschlossen]

136

Ich kann keine zugänglichen Beispiele finden, die zeigen, wie zwei (oder mehr) verschiedene Module miteinander verbunden sind, um zusammenzuarbeiten.

Ich möchte also fragen, ob jemand Zeit hat, ein Beispiel zu schreiben, in dem erklärt wird, wie Module zusammenarbeiten.

Srle
quelle
Dies hat sich in den letzten vier Jahren geändert, aber dank der eifrigen Übermoderation bleiben diese veralteten Informationen für immer erhalten . Hier ist die MDN-Seite zu ES6-Modulen.
Bbsimonbb

Antworten:

256

Um sich dem modularen Entwurfsmuster zu nähern, müssen Sie zuerst dieses Konzept verstehen:

Sofort aufgerufener Funktionsausdruck (IIFE):

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

Es gibt zwei Möglichkeiten, wie Sie die Funktionen verwenden können. 1. Funktionsdeklaration 2. Funktionsausdruck.

Hier verwenden Sie Funktionsausdruck.

Was ist ein Namespace? Wenn wir nun den Namespace zum obigen Code hinzufügen, dann

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

Was ist Schließung in JS?

Wenn wir also eine Funktion mit einem variablen Bereich / innerhalb einer anderen Funktion deklarieren (in JS können wir eine Funktion innerhalb einer anderen Funktion deklarieren!), Wird dieser Funktionsumfang immer gezählt. Dies bedeutet, dass jede Variable in der äußeren Funktion immer gelesen wird. Die globale Variable (falls vorhanden) mit demselben Namen wird nicht gelesen. Dies ist auch eines der Ziele der Verwendung eines modularen Entwurfsmusters zur Vermeidung von Namenskonflikten.

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

Jetzt werden wir diese drei oben erwähnten Konzepte anwenden, um unser erstes modulares Entwurfsmuster zu definieren:

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 für den obigen Code.

Ziel ist es, die variable Zugänglichkeit vor der Außenwelt zu verbergen.

Hoffe das hilft. Viel Glück.

kta
quelle
Wäre es besser, das Leben zu nennen? für semantische Zwecke und bessere Stapelverfolgung? würde es etwas im Code ändern?
Jeroen
2
Ihr erstes Beispiel (function() { /* Your code goes here */}());ist tatsächlich ein IIFE (sofortiges Aufrufen eines Funktionsausdrucks). OK, es ist anonym, da es keinen Namen hat. Sie können es sogar als IIAFE (sofortiges Aufrufen eines anonymen Funktionsausdrucks) bezeichnen. Weitere Informationen zu IIFE finden
Adrien Be
Warum wurde die return-Anweisung verwendet? Wenn wir return {} weglassen, ist die Funktion zum Hinzufügen und Zurücksetzen öffentlich und ich denke, sie können auf die lokale Variablensumme zugreifen. habe ich recht?
Mou
Ihr zweites Beispiel sieht aus wie ein Objekt oder ich bin nicht richtig?
Der Grund
4
Dies geht nicht auf die Frage des OP ein. Es ist eine Beschreibung des Modulmusters und kein Beispiel dafür, wie mehrere Module zusammenarbeiten können, wie es das OP wünscht.
Erik Trautman
39

Ich würde wirklich jedem empfehlen, der dieses Thema betritt, um Addy Osmanis kostenloses Buch zu lesen:

"Lernen von JavaScript-Entwurfsmustern".

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

Dieses Buch hat mir sehr geholfen, als ich anfing, wartbareres JavaScript zu schreiben, und ich verwende es immer noch als Referenz. Schauen Sie sich seine verschiedenen Modulmusterimplementierungen an, er erklärt sie sehr gut.

Code Novitiate
quelle
Ich würde auch empfehlen, meinen Artikel über das "Definitive Module Pattern" zu lesen, der nicht in Addy
Osmanis
1
Wie ist das im Vergleich zu "JavaScript Patterns" von Stoyan Stefanov
JohnMerlino
4
Stoyans Buch ist viel umfassender. Es behandelt mehr als nur Muster auf hoher Ebene, sondern geht auch ausführlicher auf andere Best Practices von JS ein.
Code Novitiate
1
Bewertungen von "Learning JavaScript Design Patterns" amazon.com/product-reviews/1449331815
Adrien Be
3
Rezensionen zu "JavaScript Patterns" von Stoyan Stefanov amazon.com/product-reviews/0596806752 . Hinweis:
Adrien Be
19

Ich dachte, ich würde die obige Antwort erweitern, indem ich darüber spreche, wie Sie Module in eine Anwendung einfügen würden. Ich hatte darüber im Doug Crockford-Buch gelesen, aber als Neuling in Javascript war alles noch ein bisschen mysteriös.

Ich komme aus ac # Hintergrund, habe also eine Terminologie hinzugefügt, die ich von dort aus nützlich finde.

Html

Sie haben eine Art HTML-Datei der obersten Ebene. Es ist hilfreich, sich dies als Ihre Projektdatei vorzustellen. Jede Javascript-Datei, die Sie dem Projekt hinzufügen, möchte darauf eingehen. Leider erhalten Sie dafür keine Tool-Unterstützung (ich verwende IDEA).

Sie müssen dem Projekt Dateien mit folgenden Skript-Tags hinzufügen:

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

Es scheint, dass das Reduzieren der Tags dazu führt, dass Dinge fehlschlagen - obwohl es so aussieht, als ob XML wirklich etwas mit verrückteren Regeln ist!

Namespace-Datei

MasterFile.js

myAppNamespace = {};

das ist es. Dies dient nur zum Hinzufügen einer einzelnen globalen Variablen, in der der Rest unseres Codes leben soll. Sie können hier (oder in eigenen Dateien) auch verschachtelte Namespaces deklarieren.

Modul (e)

SomeComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

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

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

Wir weisen hier einer Variablen in unserer Anwendung eine Nachrichtenzählerfunktion zu. Es ist eine Funktion, die eine Funktion zurückgibt, die wir sofort ausführen .

Konzepte

Ich denke, es ist hilfreich, sich die oberste Zeile in SomeComponent als den Namespace vorzustellen, in dem Sie etwas deklarieren. Die einzige Einschränkung besteht darin, dass alle Ihre Namespaces zuerst in einer anderen Datei angezeigt werden müssen - es handelt sich lediglich um Objekte, die von unserer Anwendungsvariablen verwurzelt werden.

Ich habe nur kleine Schritte mit diesem zur Zeit genommen (ich bin Refactoring einige normale Javascript aus einer extjs App , damit ich es testen kann) , aber es scheint ganz nett , wie Sie kleine Funktionseinheiten unter Vermeidung der Morast definieren : ‚Diese ' .

Sie können diesen Stil auch verwenden, um Konstruktoren zu definieren, indem Sie eine Funktion zurückgeben, die ein Objekt mit einer Sammlung von Funktionen zurückgibt und es nicht sofort aufruft.

JonnyRaa
quelle
6

Hier https://toddmotto.com/mastering-the-module-pattern finden Sie das Muster ausführlich erklärt. Ich möchte hinzufügen, dass das zweite an modularem JavaScript darin besteht, Ihren Code in mehrere Dateien zu strukturieren. Viele Leute raten Ihnen hier vielleicht, sich für AMD zu entscheiden, aber ich kann aus Erfahrung sagen, dass Sie aufgrund zahlreicher HTTP-Anfragen irgendwann mit einer langsamen Seitenantwort enden werden. Der Ausweg ist die Vorkompilierung Ihrer JavaScript-Module (eines pro Datei) in eine einzelne Datei gemäß dem CommonJS-Standard. Schauen Sie sich hier Beispiele an http://dsheiko.github.io/cjsc/

Dmitry Sheiko
quelle
Alle AMD-Implementierungen bieten auch eine Vorkompilierung in eine einzelne Datei.
I-Lin Kuo
1
Das ist richtig, aber für die resultierende optimierte Datei ist die Loader-Bibliothek erforderlich (einfach mit r.js v2.1.14 erneut überprüft), was normalerweise ziemlich gewichtig ist. Sobald wir Code kompiliert haben, müssen wir keine asynchron geladenen Abhängigkeiten auflösen, wir brauchen diese Bibliothek nicht. Denken Sie nur daran: Wir verpacken Module in AMD, das heißt asynchron. Laden Sie sie, kompilieren Sie sie dann in eine einzelne Datei (kein separates Laden mehr), laden Sie jedoch die gesamte Bibliothek, um sie zu adressieren (was jetzt redundant ist). Das klingt für mich nicht nach einem optimalen Weg. Warum überhaupt AMD, wenn wir nicht asynchron laden?
Dmitry Sheiko
almond.js bietet einen Lader mit geringerem Gewicht für den fertigen Produktionscode als RequireJS, aber vergleichsweise überwiegt der Leistungsvorteil, wenn nicht nur eine einzige http-Anfrage gestellt wird, die Kosten für das Hinzufügen des Loader-Codes zum Modul bei weitem in einem viel kleineren Maßstab. Die Frage sollte meiner Meinung nach umgedreht werden - warum Synchronizität annehmen, wenn der Browser dies nicht tut? Ich bin eigentlich der Meinung, dass sowohl RequireJS als auch CommonJS eine vielversprechende Implementierung haben sollten.
I-Lin Kuo
Beide Formate sind gültige Pfade zu CommonJS Modules / 2.0 und bieten die gleiche Skalierbarkeit. Für mich ist der Umgang mit CJS Modules / 1.1 (das meine ich mit CommonJS) viel einfacher, Code sieht sauberer aus.
Dmitry Sheiko
Ich habe folgende Vorteile von AMD kennengelernt: * kann mehr als nur JavaScript-Dateien laden; * Pfad-Aliase; Nun, CommonJS Compiler löst diese Probleme - er lädt Nicht-JavaScipt / JSON-Abhängigkeiten als Daten und kann mit einer Build-Konfiguration (einschließlich Aliasen) versehen werden. Der einzige Nachteil, dass es Gebäude erfordert. Aber heutzutage baut sowieso jeder das Projekt für CSS-Vorprozessoren. Es geht also nur darum, eine zusätzliche Aufgabe für Grunt / Gulp
hinzuzufügen