I think I'm badly misunderstanding how to use module.exports. It seems every module is overwriting what the last one spit out.
app.js:
var express = require("express")
, app = express()
, routes = require('routes')
, server = app.listen(1337, "0.0.0.0")
, io = require('socket.io').listen(server)
, redis = require("redis")
, client = redis.createClient();
var moduleA = require("./moduleA")(io, client);
(need to pass socket.io and redis client)
var moduleB = require("./moduleB")(io, client);
(same)
moduleA.js:
module.exports = function(io, client){
this.test = 'foo';
return this;
};
moduleB.js:
module.exports = function(io, client){
this.test = 'bar';
return this;
};
back to app.js:
console.log(moduleB.test);
(prints "bar")
console.log(moduleA.test);
(also prints "bar")
Could someone explain what I'm doing wrong? I can't think of any other way to do this, since the exports
helper (?) itself doesn't seem to accept parameters.
You are exporting a constructor. You need to construct it, not call it.
Change
var moduleA = require("./moduleA")(io, client);
to
var moduleA = new (require("./moduleA"))(io, client);
or (for clarity)
var ModuleA = require("./moduleA");
var a = new ModuleA(io, client);
What you are seeing happen is the usual behavior when calling constructors as functions in sloppy mode: this
references the global object. So of course modifying the global object from two locations will overwrite each other, and returning this
will just return the global object. You can test this yourself: with your current code,
moduleA === moduleB === this === global
One way to prevent yourself from ever shooting yourself in the foot like this again is to use strict mode instead of sloppy mode. To do so, add the line
"use strict";
at the top of every module you write (before any other code). In strict mode, this
for constructors called without new
is undefined
, so you will get an earlier and much easier-to-understand error.
Strict mode has many benefits of this sort; for an overview see [1], [2], [3].
An alternate solution is to stop using constructors altogether, but instead use factory functions. This would look like:
module.exports = function (io, client) {
var result = {};
result.test = "foo";
return result;
};
You seem to be trying to do something like this anyway, since you return this
even though doing so in a constructor is entirely unnecessary. You could just stop using this
and use an actual object under your control, instead of one whose semantics change depending on whether your function is being called or constructed.