【问题标题】:Node.js EventEmitter and multiple levels of inheritanceNode.js EventEmitter 和多级继承
【发布时间】:2013-07-21 12:40:33
【问题描述】:

我正在尝试找出在使用 Node.js EventEmitter 类时实现多级继承的最佳方法。

设置是我正在使用可以具有基本控制器的控制器为 Node.js 开发 MVC 框架,但控制器可以发出事件,这些事件也可以在其基本控制器上发出相同的事件。到目前为止,我有:

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

var Controller = function() { };
util.inherits(Controller, events.EventEmitter);

var baseController = new Controller();
baseController.on('request', function() {
    console.log('Calling request event on baseController');
});



var homeController = new Controller();
homeController.prototype = baseController;

homeController.on('request', function() {
   console.log('Calling request event on homeController'); 
});


homeController.emit('request');

...但仅输出“在 homeController 上调用请求事件”,我希望两个“请求”事件都触发。我该怎么做呢?也许我需要彻底改变我的方法?


更新:感谢大家的帮助。正如 Naor Biton 所建议的,baseController 和 homeController 之间没有继承关系,因为“原型”属性只对构造函数很重要。我总是把我的构造函数和对象实例搞混了。

我最终解决了以下问题:

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

var Controller = function() { };
util.inherits(Controller, events.EventEmitter);

Controller.createBaseController = function() {
    var BaseController = function() { };
    util.inherits(BaseController, Controller);

    return new BaseController();
};

Controller.inheritController = function(baseController) {
    var NewController = function() { };
    NewController.prototype = baseController;

    return new NewController();
};


var baseController = Controller.createBaseController();

baseController.on('request', function() {
    console.log('Calling request event on baseController');
});


var homeController = Controller.inheritController(baseController);

homeController.on('request', function() {
   console.log('Calling request event on homeController');
});


homeController.emit('request');

【问题讨论】:

  • 这听起来不太像(原型)继承,而更像是复合模式。

标签: javascript node.js prototypal-inheritance eventemitter


【解决方案1】:

在您的示例中,homeControllerbaseController 之间没有任何继承关系。另外,这一行:

homeController.prototype = baseController;

是多余的,因为原型属性只对构造函数很重要。

如果您想设置 baseController 以便从它扩展/继承的任何人都将分配给它的“请求”侦听器,首先您应该像这样定义它:

var BaseController = function(){
    this.on('request', function(){
       console.log('...');
    });
};

BaseController.prototype = new events.EventEmitter();
BaseController.prototype.constructor = BaseController;

如果您可以在初始化方法中进行处理程序分配会更好(在构造函数中工作通常是糟糕的设计):

var BaseController = function(){};

BaseController.prototype = new events.EventEmitter();
BaseController.prototype.init = function(){
    this.on('request', function(){
       console.log('...');
    });
};

然后,您只需在 HomeController 中扩展它即可:

var HomeController = function(){};
HomeController.prototype = new BaseController();

var homeController = new HomeController();
homeController.init(); // If you went with the initialization approach I offered...

请注意,除非您必须这样做,否则在 JS 中创建长继承链并不是很好或可维护的。如果可以的话,我鼓励您避免这样做,并尝试寻找更易于维护的解决方案。

【讨论】:

    【解决方案2】:

    在您的示例中,homeControllerbaseController 具有相同的原型(您可以使用 getPrototypeOf 进行验证。.prototype is an attributes of functions

    如果您想直接将一个对象的原型设置为另一个对象,而不使用函数并设置其原型,您可以使用Object.create

    顺便说一下,这是我在你的情况下要做的(使用更少的原型继承和更多的结构子类型)。

    function Controller(){
        var obj = new events.EventEmitter();
        // Add stuff to controller here
        obj.on("request",function(){
                console.log('Calling request event on baseController');
        });
        return obj;
    }
    function HomeController(){
        var obj = new Controller();
        obj.on('request', function() {
            console.log('Calling request event on homeController'); 
        });
        return obj;
    }
    
    var homeController = new HomeController(); // can create a Controller and add 
                                               // an event just fine. If you want explicit
                                               // structural subtyping we need HomeController
    homeController.emit("request");
    

    【讨论】:

    • 在您的示例中,在 var obj = new Controller(); 之后, obj 没有在任何地方使用。那么HomeControllerController有什么关系呢?
    • @NaorBiton 谢谢,缺少回报 :)
    • @NaorBiton 你对这篇文章的编辑被拒绝了(审稿人可能错过了这里的 cmets),我现在已经修复了 - 谢谢 agian。
    猜你喜欢
    • 2012-02-12
    • 2016-04-30
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多