Javascript: Modulmuster vs Konstruktor / Prototyp-Muster?

77

Ich würde gerne wissen, ob das Modulmuster oder das Konstruktor- / Prototypmuster für meine Arbeit besser geeignet ist.

Grundsätzlich verwende ich unauffälliges Javascript - das HTML-Dokument enthält einen Verweis auf die .js-Datei.

Mein Verständnis des Modulmusters:

  • Rufen Sie eine INIT-Methode auf (die im Grunde eine öffentliche Methode ist, die ich mithilfe des Modulmusters erstellen und zurückgeben kann).
  • Weisen Sie in der INIT-Methode alle Klickereignisse usw. zu.

Dies klingt nach dem perfekten Muster für meine Situation, da ich keine Objekte und Vererbungshierarchien usw. erstellen muss.

Mein Verständnis des Konstruktor / Prototyp-Musters:

  • zum Erstellen von Objekten
  • zur Verwendung der Vererbung (dh Subtypen eines Supertyps)

Stimmt es, dass für die Bereitstellung von unauffälligem Javascript das Modulmuster ideal ist?

Martin
quelle

Antworten:

69

Konstruktorfunktionen und Prototypen sind eine der vernünftigen Möglichkeiten, Klassen und Instanzen zu implementieren. Sie entsprechen nicht ganz diesem Modell, daher müssen Sie normalerweise ein bestimmtes Schema oder eine bestimmte Hilfsmethode auswählen, um Klassen in Bezug auf Prototypen zu implementieren. ( Einige Hintergrundinformationen zu Klassen in JS .)

Das Modulmuster wird normalerweise für den Namespace verwendet, bei dem eine einzelne Instanz als Speicher für die Gruppierung verwandter Funktionen und Objekte fungiert. Dies ist ein anderer Anwendungsfall als das, wofür Prototyping gut ist. Sie konkurrieren nicht wirklich miteinander; Sie können beide sehr gerne zusammen verwenden (z. B. eine Konstruktorfunktion in ein Modul einfügen und sagen new MyNamespace.MyModule.MyClass(arguments)).

Bobince
quelle
1
In meinem Fall möchte ich also keine Instanzen erstellen, daher ist das Modulmuster wahrscheinlich ideal für das, was ich möchte. Wenn Sie Namespace sagen. Wie kann ich einen Namespace in einem Modulmuster erstellen? Ich habe einen Weg mit YUI gesehen - aber ist das wirklich notwendig?
Martin
16
Es gibt keinen bestimmten Trick, Sie verwenden nur ein JavaScript Objectals Suche. Erstellen Sie entweder ein Objektliteral direkt wie var MyModule= { someProperty: 3, someFunction: function() { ... }, somethingElse: null };oder weisen Sie es zu MyModule.someFunction= function() { ... };. Wenn Sie private Variablen wollen, tun Sie dies in einem sofort aufgerufenen Funktionsausdruck und haben das returnObjekt in einem Abschluss ... persönlich finde ich 'echte' private Variablen eine völlige Zeitverschwendung.
Bobince
1
Die Idee, dass js Klassen hat, kann sehr irreführend sein - dies ist ein ausgezeichnetes Buch zum Thema You Don't Know JS | This & Object Prototypes - Trotz der Tatsache, dass ES6 "Klassen" unterstützt, sind diese meist nur eine Maske über die Funktionalität von Prototypen, und wenn Sie diese als Klassen in dem Sinne betrachten, dass Sie an Klassen in Java oder C # denken, werden Sie auf dem Laufenden gehalten Weg zur Verwirrung. Bei Verwendung des Prototyps schlage ich das OOLO-Muster vor, wie in Kapitel 6 des oben verlinkten Buches beschrieben.
Jordanien
1
Ich würde auch vorschlagen, dass die Idee der Vererbung in js etwas falsch ist und Delegation ein besserer Begriff ist: chipersoft.com/p/inheritance . Ich bin damit einverstanden, dass das Modulmuster nützlich ist, um komplexe Anwendungen sauber voneinander zu trennen, aber es gibt viele gute Fälle, um das Modulmuster für die Komposition / Erweiterung zu verwenden, insbesondere wenn Sie mit Entwicklern arbeiten, die mit js nicht so vertraut sind - es ist wahrscheinlich einfacher für sie Um zu verstehen, was ein IIFE ist, muss der Prototyp (wirklich) verstanden werden: angemessen
Jordanien
5
@bobince Ich weiß, dass Sie dies vor langer Zeit gepostet haben, aber warum empfinden Sie echte private Variablen als Zeitverschwendung?
PDN
13

Das Modulmuster ist weitaus einfacher und eleganter als der Prototyp. Denken Sie jedoch zuerst mobil. Es ist kein relevantes Muster für mittlere / große Objekte, da bei der Initialisierung vor dem Start der gesamte Block analysiert werden muss. Die mehrfachen Schließungen erzeugen auch kreisförmige Abhängigkeiten, die der Garbage Collector nicht freigibt (insbesondere IE). Dies führt zu einem größeren Speicherbedarf, der erst freigegeben wird, wenn das Fenster (oder die Registerkarte) geschlossen wird. Überprüfen Sie den Chrome-Task-Manager, um zu vergleichen. Die Ladezeit ist umgekehrt proportional zur Objektgröße unter Verwendung des Modulmusters, während dies bei der prototypischen Vererbung nicht der Fall ist. Die obigen Aussagen werden durch mehrere Benchmarks wie diesen überprüft: http://jsperf.com/prototypal-performance/54

Wie im letzten Test gesehen. Kleine Objekte sollten besser als einfaches Objekt initialisiert werden (ohne diese Muster). Es eignet sich für einzelne Objekte, die weder geschlossen noch vererbt werden müssen. Es ist ratsam zu beurteilen, ob Sie diese Muster überhaupt benötigen.

Yann VR
quelle
4

Das Prototypmuster hilft uns, die Funktionalität zu erweitern, und es gibt nur eine Instanz von Funktionen in einem Speicher, unabhängig von der Anzahl der Objekte. In Module patter erstellt jedes Objekt eine neue Instanz von Funktionen im Speicher, bietet jedoch ein Konzept für private / öffentliche Variablen und hilft bei der Kapselung der Variablen und Funktionen.

user1662008
quelle
Was ist mit Douglas Crockfords privilegierter Klassenmethode, die die Verwendung privater Mitglieder ermöglicht?
Wayofthefuture