Node.js EventEmitter和多级继承

时间:2013-07-21 12:40:33

标签: javascript node.js prototypal-inheritance eventemitter

在使用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之间没有继承,因为'prototype'属性仅对构造函数有用。我总是让我的构造函数和对象实例混淆。

我最终解决了以下问题:

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

2 个答案:

答案 0 :(得分:3)

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

homeController.prototype = baseController;

是多余的,因为prototype属性仅对构造函数有用。

如果你想设置 baseController ,那么无论谁扩展/继承它都会为它分配'request'监听器,首先应该像这样定义它:

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

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

如果你可以在initiliazation方法中进行处理程序赋值会更好(在构造函数中工作通常是糟糕的设计):

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中创建长继承链不是很好或可维护。如果可以,我鼓励您避免这样做,并尝试寻找更易于维护的解决方案。

答案 1 :(得分: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");