jef*_*eon 84 node.js eventemitter
我在很多Node.js库中看到了这种模式:
Master.prototype.__proto__ = EventEmitter.prototype;
Run Code Online (Sandbox Code Playgroud)
(来源这里)
有人可以用一个例子向我解释,为什么这是一个如此常见的模式,什么时候它很方便?
ale*_*lex 80
正如代码上面的注释所说,它将Master继承EventEmitter.prototype,因此您可以使用该"类"的实例来发出和侦听事件.
例如,你现在可以这样做:
masterInstance = new Master();
masterInstance.on('an_event', function () {
console.log('an event has happened');
});
// trigger the event
masterInstance.emit('an_event');
Run Code Online (Sandbox Code Playgroud)
更新:正如许多用户指出的那样,在Node中执行此操作的"标准"方法是使用'util.inherits':
var EventEmitter = require('events').EventEmitter;
util.inherits(Master, EventEmitter);
Run Code Online (Sandbox Code Playgroud)
Bre*_*dly 77
这些直接来自文档,但我认为将它们添加到这个流行的问题对任何人看都很好.
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');
Run Code Online (Sandbox Code Playgroud)
我想constructor()添加任何人.事件发射器.
注意:文档不会MyEmitter在构造函数中调用,这将导致super()未定义.看到这个问题.
met*_*att 39
要继承另一个Javascript对象,特别是Node.js的EventEmitter,但实际上通常是任何对象,你需要做两件事:
[[proto]]从构造函数创建的对象; 如果您从其他对象继承,您可能希望使用另一个对象的实例作为原型.这在Javascript中比在其他语言中看起来更复杂,因为
对于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);
Run Code Online (Sandbox Code Playgroud)
可能的缺点:
util.inherits,但不要EventEmitter为您的类的实例调用超级构造函数(),它们将无法正确初始化.new EventEmitter)的初始化实例,Master.prototype而不是让子类构造函数Master调用超级构造函数EventEmitter; 取决于超类构造函数的行为,可能看起来它在一段时间内工作正常,但不是同一件事(并且不适用于EventEmitter).Master.prototype = EventEmitter.prototype),而不是通过Object.create添加额外的对象层; 这可能看起来像是工作正常,直到有人monkeypatches你的对象Master,并无意中也monkeypatched EventEmitter和所有其他后代.每个"类"都应该有自己的原型.再次:要继承EventEmitter(或实际上任何现有对象"class"),您需要定义一个构造函数,该构造函数链接到超级构造函数并提供从超级原型派生的原型.
Daf*_*aff 19
这就是在JavaScript中完成原型(原型?)继承的方式.来自MDN:
引用对象的原型,可以是对象或null(通常意味着对象是Object.prototype,它没有原型).它有时用于实现基于原型继承的属性查找.
这也有效:
var Emitter = function(obj) {
this.obj = obj;
}
// DON'T Emitter.prototype = new require('events').EventEmitter();
Emitter.prototype = Object.create(require('events').EventEmitter.prototype);
Run Code Online (Sandbox Code Playgroud)
理解JavaScript OOP是我最近在ECMAScript 5中阅读OOP的最佳文章之一.
我认为这种方法来自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 );
}
Run Code Online (Sandbox Code Playgroud)
Douglas Crockford也有一些有趣的继承模式:http://www.crockford.com/javascript/inheritance.html
我发现在JavaScript和Node.js中经常不需要继承.但在编写一个继承可能会影响可伸缩性的应用程序时,我会考虑性能与可维护性的权衡.否则,我只会决定哪些模式可以带来更好的整体设计,更易于维护,更不容易出错.
在jsPerf中测试不同的模式,使用Google Chrome(V8)进行粗略比较.V8是Node.js和Chrome使用的JavaScript引擎.
这里有一些jsPerfs可以帮助你入门:
http://jsperf.com/prototypes-vs-functions/4
http://jsperf.com/inheritance-proto-vs-object-create
http://jsperf.com/inheritance-perf