Je vois ce modèle dans pas mal de bibliothèques Node.js:
Master.prototype.__proto__ = EventEmitter.prototype;
(source ici )
Est-ce que quelqu'un peut m'expliquer avec un exemple, pourquoi c'est un modèle si courant et quand c'est pratique?
Comme le commentaire ci-dessus, ce code indique que Master
héritera de EventEmitter.prototype
, vous pouvez donc utiliser des instances de cette "classe" pour émettre et écouter des événements.
Par exemple, vous pouvez maintenant faire:
masterInstance = new Master();
masterInstance.on('an_event', function () {
console.log('an event has happened');
});
// trigger the event
masterInstance.emit('an_event');
Mise à jour: comme de nombreux utilisateurs l'ont souligné, la méthode "standard" pour le faire dans Node serait d'utiliser "util.inherits":
var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);
Celles-ci proviennent directement de la documentation, mais j’ai pensé qu’il serait bien de les ajouter à cette question populaire pour ceux qui cherchent.
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {
constructor() {
super(); //must call super for "this" to be defined.
}
}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
J'aimerais bien git thank
Qui l'a ajouté. émetteur d'événements .
Remarque: La documentation n'appelle pas super()
dans le constructeur, ce qui entraînera la non-définition de this
. Voir ceci issue .
Pour hériter d'un autre objet Javascript, notamment de EventEmitter de Node.js mais vraiment de n'importe quel objet en général, vous devez faire deux choses:
[[proto]]
pour les objets créés à partir de votre constructeur; dans le cas où vous héritez d'un autre objet, vous souhaiterez probablement utiliser une instance de l'autre objet comme prototype.C’est plus compliqué en Javascript qu’il pourrait sembler en d’autres langues car
Pour le cas spécifique de EventEmitter de Node.js, voici ce qui fonctionne:
var EventEmitter = require('events').EventEmitter;
var util = require('util');
// Define the constructor for your derived "class"
function Master(arg1, arg2) {
// call the super constructor to initialize `this`
EventEmitter.call(this);
// your own initialization of `this` follows here
};
// Declare that your class should use EventEmitter as its prototype.
// This is roughly equivalent to: Master.prototype = Object.create(EventEmitter.prototype)
util.inherits(Master, EventEmitter);
Défis possibles:
util.inherits
, mais n’appelez pas le super constructeur (EventEmitter
) pour les instances de votre classe, elles ne seront pas correctement initialisées.new EventEmitter
) comme Master.prototype
au lieu d'avoir le constructeur de sous-classe Master
appeler le super constructeur EventEmitter
; En fonction du comportement du constructeur de la super-classe, cela peut sembler fonctionner pendant un certain temps, mais ce n'est pas la même chose (et cela ne fonctionnera pas pour EventEmitter).Master.prototype = EventEmitter.prototype
) au lieu d’ajouter une couche d’objet supplémentaire via Object.create; cela peut sembler fonctionner correctement jusqu'à ce que quelqu'un clippe votre objet Master
et ait aussi par inadvertance monkeypatched EventEmitter
et tous ses autres descendants. Chaque "classe" devrait avoir son propre prototype.Encore une fois: pour hériter de EventEmitter (ou de tout objet "classe" existant), vous souhaitez définir un constructeur qui se lie au super constructeur et fournit un prototype dérivé du super prototype.
C'est comment l'héritage prototypique (prototypal?) Se fait en JavaScript. De MDN :
Fait référence au prototype de l'objet, qui peut être un objet ou null (ce qui signifie généralement que l'objet est Object.prototype, qui n'a pas de prototype). Il est parfois utilisé pour implémenter une recherche de propriété basée sur un héritage prototype.
Cela fonctionne aussi bien:
var Emitter = function(obj) {
this.obj = obj;
}
// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);
Comprendre le langage OOP JavaScript est l’un des meilleurs articles que j’ai récemment lu sur OOP dans ECMAScript 5.
Je pensais que cette approche de http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm était plutôt soignée :
function EventedObject(){
// Super constructor
EventEmitter.call( this );
return( this );
}
Douglas Crockford a également des modèles d’héritage intéressants: http://www.crockford.com/javascript/inheritance.html
Je trouve que l'héritage est moins souvent nécessaire dans JavaScript et Node.js. Mais en écrivant une application où l'héritage peut affecter l'évolutivité, je considérerais les performances mises en balance avec la maintenabilité. Sinon, je ne fonderais ma décision que sur les modèles qui conduiraient à de meilleures conceptions globales, qui seraient plus faciles à gérer et moins sujets aux erreurs.
Testez différents modèles dans jsPerf, en utilisant Google Chrome (V8) pour obtenir une comparaison approximative. V8 est le moteur JavaScript utilisé par Node.js et Chrome.
Voici quelques jsPerfs pour vous aider à démarrer:
http://jsperf.com/prototypes-vs-functions/4
Pour ajouter à la réponse de wprl. Il a raté la partie "prototype":
function EventedObject(){
// Super constructor
EventEmitter.call(this);
return this;
}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part