1

Why are these two variables (1) and (2) not equivalent:

    var EventEmitter = require('events').EventEmitter;

(1) var ee = new EventEmitter();

(2) var ee = new require('events').EventEmitter();

variables (1) and (2) are not the same, and I can't figure out why that is.

However, these two are equivalent (a) and (b):

   var EventEmitter = require('events').EventEmitter;

(a) var ee = new EventEmitter();

(b) var ee = new (require('events').EventEmitter)();

Could someone explain why this is?

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817

2 Answers2

3

Updated

There are two things here.

1. Using the EventEmitter API

I think you're asking why ee1 !== ee2 using the API.

They're different because the API let's you create as many EventEmitter's as you like.

This let's you have an EventEmitter for multiple sockets, streams, db connections, or whatever you need.

You could think of new EventEmitter() as a factory stamping out EventEmitter's

2. If you're asking about this specific code, there's a bug in the 2nd version.

The bug is due to JavaScript's Operator Order.

Tl;DR, you need ()'s around the . for a one-line new:

var ee4 = new (require('events').EventEmitter);
              (                 .            )   <-- do . before new

The issue is that new and . have the same precidence so are evaluated left-to-right. That precedence puts it above or below the . operator after require('events').

This code helped me understand better node test.js:

var EventEmitter = require('events').EventEmitter;
console.log('require(\'events\').EventEmitter: ' + EventEmitter);

// Works
var ee1 = new EventEmitter;
console.log('ee1: new EventEmitter: ' + ee1);  

// Works
var ee1a = new EventEmitter();
console.log('ee1a: new EventEmitter(): ' + ee1a);  

// Desn't work.  Appears to be the constructor.
var ee2 = new require('events').EventEmitter;
console.log('ee2: new require(\'events\').EventEmitter: ' + ee2);  

// Doesn't work.  Undefined
var ee3 = new require('events').EventEmitter();
console.log('ee3: new require(\'events\').EventEmitter(): ' + ee3);  

// Works.  'one-liner'
var ee4 = new (require('events').EventEmitter);
console.log('ee4: new (require(\'events\').EventEmitter): ' + ee4);

// Works.  'one-liner' with parameters
var ee4a = new (require('events').EventEmitter)();
console.log('ee4: new (require(\'events\').EventEmitter)(): ' + ee4a);

// Doesn't work.  Undefined
var ee5 = require('events').EventEmitter();
console.log('ee5: require(\'events\').EventEmitter(): ' + ee5);
Michael Cole
  • 15,473
  • 7
  • 79
  • 96
2

These two versions are fundamentally different.

This one:

var EventEmitter = require('events').EventEmitter;
var ee = new EventEmitter();

Executes the require, returning the exports of events and then calling the new operator on the results .

This one:

var ee = new require('events').EventEmitter;

Invokes require as a constructor.

Look at a more isolated and simple example:

new Date() // creates a new date object

new (Date()) // throws a TypeError: string is not a function

Dayton Wang
  • 2,332
  • 1
  • 12
  • 17
  • Parentheses do not add anything there `new (require('events')).EventEmitter` is identical to `new require('events').EventEmitter` because of operator precedence. – zerkms Apr 30 '15 at 00:37