Node.js - 从模块发出事件的最佳方法

时间:2011-07-31 21:28:00

标签: events javascript-events node.js

我一直在玩EventEmitter,但我对如何从模块实现它感到困惑。我见过几种不同的方式,它们似乎都有效。以下是我见过的一些内容:

来自here

var Twitter = function() {...};

Twitter.prototype = new events.EventEmitter;

然后在"Mastering Node"他们这样做:

function Dog(name) {
  this.name = name;
  EventEmitter.call(this);
}

Dog.prototype.__proto__ = EventEmitter.prototype;

(为什么你需要.call它?)

然后在我自己的代码中我尝试了另一种方式:

function Class() {}

Class.prototype = EventEmitter.prototype;

他们都只是以自己的方式从EventEmitter继承,所以最简单的解决方案不是最好的吗?

2 个答案:

答案 0 :(得分:20)

Node有一个库函数util.inherits,它比接受的答案稍微简单一些。以下代码是从v0.8.12 docs修改的。

var util = require("util");
var events = require("events");

function MyStream() {
  events.EventEmitter.call(this);
}

util.inherits(MyStream, events.EventEmitter);

答案 1 :(得分:18)

您应该使用__proto__继承方式。 This assumes you're coding solely for Node, or only supporting your favorite browsers。此外,如果您关心基础原型的构造函数中的任何逻辑,则Base.call(this)是必需的。

引用基础原型的__proto__技术将确保instanceof运算符正确识别原型的实例。子的实例的.constructor属性将引用您期望它的构造函数。它还具有不实例化基本原型的新实例的好处。

new Base()样式还将确保instanceof为您提供正确答案,但它将运行Base的构造函数。通常不是问题,但如果您的基础构造函数具有必需参数,则可能会出现问题。它还会将.constructor属性设置为基础构造函数not the descendant constructor

的原型设置为基本的原型会使instanceof混淆,因为基类的任何后代也将显示为孩子。

清楚如泥,对吗?这个例子应该有所帮助:

// Base constructor.
// A, B, and C will inherit from Base.
function Base() {
    this.name = 'base';
}

// new Base() style
function A() {
    Base.call(this);
}
A.prototype = new Base();

// __proto__ = prototype style
function B() {
    Base.call(this);
}
B.prototype.__proto__ = Base.prototype;

// prototype = protoype style
function C() {
    Base.call(this);
}
C.prototype = Base.prototype;

// create instances
var a = new A();
var b = new B();
var c = new C();

// are we who we think we are?
console.assert(a instanceof A);
console.assert(b instanceof B);
console.assert(c instanceof C);
// so far so good

// do we respect our elders?
console.assert(a instanceof Base);
console.assert(b instanceof Base);
console.assert(c instanceof Base);
// we have respect

// test to see that Base.call(this)
// functioned as expected
console.assert(a.name == 'base');
console.assert(b.name == 'base');
console.assert(c.name == 'base');
// ok, good...

// but now things get weird
console.assert(a instanceof C);
console.assert(b instanceof C);
// that's not right! a is not C, b is not C!

// At least A and B do not confuse identities
console.assert(!(a instanceof B));
console.assert(!(b instanceof A));

console.assert(!(c instanceof A));
console.assert(!(c instanceof B));

// so we've determined that style C is no good.
// C confuses the inheritance chain.

// B is the winner.

// Why? Only B passes this test
console.assert(b.constructor == B);

// a and c's constructors actually point to the Base constructor
console.assert(a.constructor == Base);
console.assert(c.constructor == Base);

// Word B.