Node.js - 从 EventEmitter 继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8898399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Node.js - inheriting from EventEmitter
提问by jeffreyveon
采纳答案by alessioalex
As the comment above that code says, it will make Masterinherit from EventEmitter.prototype, so you can use instances of that 'class' to emit and listen to events.
正如该代码上面的注释所说,它将Master继承自EventEmitter.prototype,因此您可以使用该“类”的实例来发出和侦听事件。
For example you could now do:
例如,您现在可以执行以下操作:
masterInstance = new Master();
masterInstance.on('an_event', function () {
console.log('an event has happened');
});
// trigger the event
masterInstance.emit('an_event');
Update: as many users pointed out, the 'standard' way of doing that in Node would be to use 'util.inherits':
更新:正如许多用户指出的那样,在 Node 中这样做的“标准”方法是使用“util.inherits”:
var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);
2nd Update: with ES6 classes upon us, it is recommended to extend the EventEmitterclass now:
第二次更新:随着 ES6 类的出现,建议EventEmitter现在扩展类:
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
回答by Breedly
ES6 Style Class Inheritance
ES6 样式类继承
The Node docs now recommendusing class inheritence to make your own event emitter:
Node 文档现在推荐使用类继承来制作你自己的事件发射器:
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {
// Add any custom methods here
}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
Note:If you define a constructor()function in MyEmitter, you should call super()from it to ensure the parent class's constructor is called too, unless you have a good reason not to.
注意:如果你在 中定义了一个constructor()函数MyEmitter,你应该调用super()它以确保父类的构造函数也被调用,除非你有充分的理由不这样做。
回答by metamatt
To inherit from another Javascript object, Node.js's EventEmitter in particular but really any object in general, you need to do two things:
要从另一个 Javascript 对象继承,特别是 Node.js 的 EventEmitter 但实际上是任何一般的对象,您需要做两件事:
- provide a constructor for your object, which completely initializes the object; in the case that you're inheriting from some other object, you probably want to delegate some of this initialization work to the super constructor.
- provide a prototype object that will be used as the
[[proto]]for objects created from your constructor; in the case that you're inheriting from some other object, you probably want to use an instance of the other object as your prototype.
- 为您的对象提供一个构造函数,它完全初始化对象;如果您从某个其他对象继承,您可能希望将一些初始化工作委托给超级构造函数。
- 提供一个原型对象,该对象将用作
[[proto]]从构造函数创建的对象;如果您从某个其他对象继承,您可能希望使用其他对象的实例作为您的原型。
This is more complicated in Javascript than it might seem in other languages because
这在 Javascript 中比在其他语言中看起来更复杂,因为
- Javascript separates object behavior into "constructor" and "prototype". These concepts are meant to be used together, but can be used separately.
- Javascript is a very malleable language and people use it differently and there is no single true definition of what "inheritance" means.
- In many cases, you can get away with doing a subset of what's correct, and you'll find tons of examples to follow (including some other answers to this SO question) that seem to work fine for your case.
- Javascript 将对象行为分为“构造函数”和“原型”。这些概念旨在一起使用,但可以单独使用。
- Javascript 是一种非常具有延展性的语言,人们以不同的方式使用它,并且对于“继承”的含义没有单一的真正定义。
- 在许多情况下,您可以避免做正确的子集,并且您会发现大量示例(包括此 SO 问题的一些其他答案)似乎适合您的案例。
For the specific case of Node.js's EventEmitter, here's what works:
对于 Node.js 的 EventEmitter 的特定情况,以下是有效的:
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);
Possible foibles:
可能的缺点:
- If you use set the prototype for your subclass (Master.prototype), with or without using
util.inherits, but don't call the super constructor (EventEmitter) for instances of your class, they won't be properly initialized. - If you call the super constructor but don't set the prototype, EventEmitter methods won't work on your object
- You might try to use an initialized instance of the superclass (
new EventEmitter) asMaster.prototypeinstead of having the subclass constructorMastercall the super constructorEventEmitter; depending on the behavior of the superclass constructor that might seem like it's working fine for a while, but is not the same thing (and won't work for EventEmitter). - You might try to use the super prototype directly (
Master.prototype = EventEmitter.prototype) instead of adding an additional layer of object via Object.create; this might seem like it's working fine until someone monkeypatches your objectMasterand has inadvertently also monkeypatchedEventEmitterand all its other descendants. Each "class" should have its own prototype.
- 如果您使用 set 为您的子类 (Master.prototype) 设置原型,无论是否使用 using
util.inherits,但不要EventEmitter为您的类的实例调用超级构造函数 ( ),它们将不会被正确初始化。 - 如果您调用超级构造函数但未设置原型,则 EventEmitter 方法将不会对您的对象起作用
- 您可能会尝试使用超类 (
new EventEmitter)的初始化实例,Master.prototype而不是让子类构造函数Master调用超构造函数EventEmitter;取决于超类构造函数的行为,它似乎可以正常工作一段时间,但不是一回事(并且不适用于 EventEmitter)。 - 您可能会尝试直接使用超级原型 (
Master.prototype = EventEmitter.prototype) 而不是通过 Object.create 添加额外的对象层;这可能看起来工作正常,直到有人对您的对象进行了猴子修补Master,并且无意中也对您的对象进行了猴子修补EventEmitter及其所有其他后代。每个“类”都应该有自己的原型。
Again: to inherit from EventEmitter (or really any existing object "class"), you want to define a constructor that chains to the super constructor and provides a prototype that is derived from the super prototype.
再次:要从 EventEmitter(或实际上任何现有的对象“类”)继承,您需要定义一个构造函数,该构造函数链接到超级构造函数并提供从超级原型派生的原型。
回答by Daff
This is how prototypical (prototypal?) inheritance is done in JavaScript. From MDN:
这就是 JavaScript 中原型(prototypal?)继承的方式。来自MDN:
Refers to the prototype of the object, which may be an object or null (which usually means the object is Object.prototype, which has no prototype). It is sometimes used to implement prototype-inheritance based property lookup.
指对象的原型,可以是对象,也可以是null(通常表示对象是Object.prototype,没有原型)。它有时用于实现基于原型继承的属性查找。
This works as well:
这也有效:
var Emitter = function(obj) {
this.obj = obj;
}
// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);
Understanding JavaScript OOPis one of the best articles I read lately on OOP in ECMAScript 5.
理解 JavaScript OOP是我最近在 ECMAScript 5 中阅读的关于 OOP 的最好的文章之一。
回答by wprl
I thought this approach from http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htmwas pretty neat:
我认为来自http://www.bennadel.com/blog/2187-Extending-EventEmitter-To-Create-An-Evented-Cache-In-Node-js.htm 的这种方法非常简洁:
function EventedObject(){
// Super constructor
EventEmitter.call( this );
return( this );
}
Douglas Crockford has some interesting inheritence patterns too: http://www.crockford.com/javascript/inheritance.html
Douglas Crockford 也有一些有趣的继承模式:http: //www.crockford.com/javascript/inheritance.html
I find inheritence is less often needed in JavaScript and Node.js. But in writing an app where inheritence might affect scalability, I would consider performance weighed against maintainability. Otherwise, I would only base my decision on which patterns lead to better overall designs, are more maintainable, and less error-prone.
我发现 JavaScript 和 Node.js 中很少需要继承。但是在编写一个继承可能会影响可扩展性的应用程序时,我会考虑性能与可维护性的权衡。否则,我只会根据哪些模式可以带来更好的整体设计、更易于维护和更不容易出错来做出决定。
Test different patterns out in jsPerf, using Google Chrome (V8) to get a rough comparison. V8 is the JavaScript engine used by both Node.js and Chrome.
在 jsPerf 中测试不同的模式,使用 Google Chrome (V8) 进行粗略比较。V8 是 Node.js 和 Chrome 使用的 JavaScript 引擎。
Here're some jsPerfs to get you started:
这里有一些 jsPerfs 可以帮助您入门:
http://jsperf.com/prototypes-vs-functions/4
http://jsperf.com/prototypes-vs-functions/4
http://jsperf.com/inheritance-proto-vs-object-create
http://jsperf.com/inheritance-proto-vs-object-create
回答by guatedude2
To add to wprl's response. He missed the "prototype" part:
添加到 wprl 的响应中。他错过了“原型”部分:
function EventedObject(){
// Super constructor
EventEmitter.call(this);
return this;
}
EventObject.prototype = new EventEmitter(); //<-- you're missing this part

