Ich sehe dieses Muster in einigen Node.js-Bibliotheken:
Master.prototype.__proto__ = EventEmitter.prototype;
(Quelle hier )
Kann mir bitte jemand anhand eines Beispiels erklären, warum dies so häufig vorkommt und wann es praktisch ist?
node.js
eventemitter
Jeffreyveon
quelle
quelle
__proto__
ist ein Anti-Muster, bitte verwenden SieMaster.prototype = Object.create(EventEmitter.prototype);
util.inherits(Master, EventEmitter);
Antworten:
Wie der Kommentar über diesem Code besagt, wird er von
Master
erbenEventEmitter.prototype
, sodass Sie Instanzen dieser 'Klasse' verwenden können, um Ereignisse auszugeben und abzuhören.Zum Beispiel könnten Sie jetzt tun:
Update : Wie viele Benutzer betonten, besteht die "Standard" -Methode in Node darin, "util.inherits" zu verwenden:
2. Update : Mit ES6-Klassen wird empfohlen, die
EventEmitter
Klasse jetzt zu erweitern:Siehe https://nodejs.org/api/events.html#events_events
quelle
require('events').EventEmitter
zuerst zu tun - ich vergesse es immer. Hier ist der Link zu den Dokumenten, falls jemand anderes es braucht: nodejs.org/api/events.html#events_class_events_eventemitter )MasterInstance
sein solltemasterInstance
.util.inherits
macht eine böse Sache, diesuper_
Eigenschaft in dasMaster
Objekt zu injizieren . Es ist unnötig und versucht, prototypische Vererbung wie klassische Vererbung zu behandeln. Weitere Informationen finden Sie am Ende dieser Seite.Master.prototype = EventEmitter.prototype;
. Keine Notwendigkeit für Supers. Sie können auch ES6-Erweiterungen (und dies wird in Node.js Dokumenten empfohlenutil.inherits
) wie folgt verwendenclass Master extends EventEmitter
- Sie werden klassischsuper()
, ohne jedoch etwas zu injizierenMaster
.Vererbung der ES6-Stilklasse
In den Node-Dokumenten wird jetzt empfohlen, die Klassenvererbung zu verwenden, um Ihren eigenen Ereignisemitter zu erstellen:
Hinweis: Wenn Sie eine
constructor()
Funktion in definierenMyEmitter
, sollten Sie sie aufrufensuper()
, um sicherzustellen, dass auch der Konstruktor der übergeordneten Klasse aufgerufen wird, es sei denn, Sie haben einen guten Grund, dies nicht zu tun.quelle
super()
ist nicht erforderlich , solange Sie keinen Konstruktor benötigen / definieren. Daher war Breedlys ursprüngliche Antwort (siehe EDIT-Verlauf) völlig korrekt. In diesem Fall können Sie dasselbe Beispiel kopieren und in die Repl einfügen, den Konstruktor vollständig entfernen und es funktioniert auf die gleiche Weise. Das ist eine vollkommen gültige Syntax.Um von einem anderen Javascript-Objekt zu erben, insbesondere von EventEmitter von Node.js, aber wirklich von jedem Objekt im Allgemeinen, müssen Sie zwei Dinge tun:
[[proto]]
für Objekte verwendet wird, die von Ihrem Konstruktor erstellt wurden. Für den Fall, dass Sie von einem anderen Objekt erben, möchten Sie wahrscheinlich eine Instanz des anderen Objekts als Prototyp verwenden.Dies ist in Javascript komplizierter als es in anderen Sprachen erscheinen mag, weil
Für den speziellen Fall von Node.js EventEmitter funktioniert Folgendes:
Mögliche Schwächen:
util.inherits
, aber den Superkonstruktor (EventEmitter
) für Instanzen Ihrer Klasse nicht aufrufen , werden sie nicht ordnungsgemäß initialisiert.new EventEmitter
) zu verwenden,Master.prototype
anstatt dass der UnterklassenkonstruktorMaster
den Superkonstruktor aufruftEventEmitter
. Abhängig vom Verhalten des Superklassenkonstruktors scheint dies für eine Weile gut zu funktionieren, ist aber nicht dasselbe (und funktioniert nicht für EventEmitter).Master.prototype = EventEmitter.prototype
) zu verwenden, anstatt über Object.create eine zusätzliche Objektebene hinzuzufügen. Dies scheint gut zu funktionieren, bis jemand Ihr ObjektMaster
monkeypatchedEventEmitter
und versehentlich auch monkeypatched und alle seine anderen Nachkommen hat. Jede "Klasse" sollte einen eigenen Prototyp haben.Nochmals: Um von EventEmitter (oder einer wirklich vorhandenen Objektklasse) zu erben, möchten Sie einen Konstruktor definieren, der mit dem Superkonstruktor verkettet ist und einen Prototyp bereitstellt, der vom Superprototyp abgeleitet ist.
quelle
So erfolgt die prototypische (prototypische?) Vererbung in JavaScript. Von MDN :
Das funktioniert auch:
Das Verständnis von JavaScript OOP ist einer der besten Artikel, die ich in letzter Zeit über OOP in ECMAScript 5 gelesen habe.
quelle
Y.prototype = new X();
ist ein Anti-Muster, bitte verwenden SieY.prototype = Object.create(X.prototype);
new X()
Instanziieren Sie eine Instanz vonX.prototype
und initialisieren Sie sie, indem Sie sie aufrufenX
.Object.create(X.prototype)
instanziiert nur eine Instanz. Sie müssen nichtEmitter.prototype
initialisiert werden. Ich kann keinen guten Artikel finden, der dies erklärt.Ich fand diesen Ansatz von http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm ziemlich ordentlich:
Douglas Crockford hat auch einige interessante Vererbungsmuster: http://www.crockford.com/javascript/inheritance.html
Ich finde, dass Vererbung in JavaScript und Node.js seltener benötigt wird. Beim Schreiben einer App, bei der die Vererbung die Skalierbarkeit beeinträchtigen könnte, würde ich jedoch die Leistung als gegen die Wartbarkeit abgewogen betrachten. Andernfalls würde ich meine Entscheidung nur darauf stützen, welche Muster zu besseren Gesamtdesigns führen, wartbarer und weniger fehleranfällig sind.
Testen Sie verschiedene Muster in jsPerf mit Google Chrome (V8), um einen groben Vergleich zu erhalten. V8 ist die JavaScript-Engine, die sowohl von Node.js als auch von Chrome verwendet wird.
Hier sind einige jsPerfs, um Ihnen den Einstieg zu erleichtern:
http://jsperf.com/prototypes-vs-functions/4
http://jsperf.com/inheritance-proto-vs-object-create
http://jsperf.com/inheritance-perf
quelle
emit
undon
komme als undefiniert heraus.Zur Antwort von wprl hinzufügen. Er vermisste den "Prototyp" Teil:
quelle
util.inherits
da viele kluge Leute diese Optionen für Sie auf dem neuesten Stand halten.