0

I have a question specific a bit to inheritance in javascript rather than node.js:

// foo.js
var events = require('events');
var util = require('util');

var Foo = (function(){
    var foo = {};
    events.EventEmitter.call(foo);
    foo.init = function(){
        foo.emit('bar');
    };

    util.inherits(parser, events.EventEmitter);

    return { 
        bind: foo.init,
        on: foo.on // I suppose this resolves to event emitter's on method
    };

}());

module.exports = Foo;

Then, when i simply try to call (say in main.js):

var foo = require('./foo.js');

foo.on('bar', function(){ ... });

An error is generated before i even call foo.init();:

foo.on('bar', function(){ ... })
       ^
TypeError: Property 'on' of object #<Object> is not a function

Isn't it possible to inherit from EventEmitter when I chose to code in IIFE pattern? Or my error is related something else?

px5x2
  • 1,495
  • 2
  • 14
  • 29

2 Answers2

2

If you want to keep this pattern, and you have a good reason for not using prototypal inheritance like this:

FooConstuctor.prototype = new events.EventEmitter();

Then, if all you need from the EventEmitter is the on method, you can just add:

Foo.on = events.EventEmitter.prototype.on;

Right after you create Foo.

You don't get the on method on Foo just by invoking EventEmitter's constructor on Foo because the on method isn't attached to EventEmitter objects in the constructor.

The reason for that is probably that it's usually considered bad practice to assign methods to your objects in their constructor, because then, a new function instance is created for each object instance which is unnecessary usually and wasteful, and methods created like this aren't directly assigned to the prototype, which can be misleading for other developers planning to extend your "class".

Naor Biton
  • 952
  • 9
  • 14
  • Nice explanation, however, I want to keep my pattern in order to encapsulate and not to provide all of my functions right away. – px5x2 Jul 20 '13 at 23:47
  • Since this is written in **Node.js**, no local variable will 'leak' out to global scope anyway, so you shouldn't worry about that. Only what's assigned to the *exports* property is available outside of the module. Besisdes, the solution I suggested takes into account that you want to keep this pattern and doesn't conflict with it. (only the second line of code is relevant). – Naor Biton Jul 21 '13 at 06:48
2

If I need an object that acts like an EventEmitter with the module pattern I prefer the following:

var foo = function () {

  var ee = new EventEmitter();

  /* custom logic */

  return {
    on: ee.on.bind(ee),
    emit: ee.emit.bind(ee),
  }

};
Pickels
  • 33,902
  • 26
  • 118
  • 178