【问题标题】:Node.js - Best method for emitting events from modulesNode.js - 从模块发出事件的最佳方法
【发布时间】:2011-10-17 01:43:11
【问题描述】:

我一直在玩 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 继承,那么最简单的解决方案不是最好的吗?

【问题讨论】:

    标签: events javascript-events node.js


    【解决方案1】:

    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);
    

    【讨论】:

    • 我有this question 这有点相关。你介意看看吗?
    • 您能否解释一下events.EventEmitter.call(this); 以及为什么这是必要的,或者是否可以忽略它?
    • @majidarif 简短的回答是调用以 MyStream 实例作为“this”变量执行 EventEmitter 函数,因此它将执行 MyStream 实例的所有 EventEmitter 初始化。希望这是有道理的。
    【解决方案2】:

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

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

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

    class 的原型设置为基 class 的原型会混淆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.
    

    【讨论】:

    • 哇,谢谢。我希望我能给这个答案不止一个赞成票。
    猜你喜欢
    • 2016-04-17
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    相关资源
    最近更新 更多