5

I don't think I quite understand how exports work in Node.js. In a bit of sample code, I noticed the exports object used in this manner:

exports = mongoose = require('mongoose')
mongoose.connect(config.db.uri)
exports = Schema = mongoose.Schema

What is happening behind the scenes when you use exports = twice like that? Looks to me like "mongoose" should not be exported. I did this quick test:

var foo
  , bar

exports = foo = 'foo'
exports = bar = 'bar'

// reports 'bar' only
console.log(exports)

and the second test does overwrite the first export.

typeoneerror
  • 55,990
  • 32
  • 132
  • 223
  • Yeah, that is strange. Usually, you would expect a `exports.foo = 'foo'` etc. – Davin Tryon Mar 09 '12 at 00:21
  • 2
    It may be possible that mongoose.Schema points to mongoose. – ming_codes Mar 09 '12 at 00:37
  • I'm just trying to figure this out myself, and as best I can tell, all 3 lines do nothing. By setting the exports object, the global exports object is lost. So, nothing is getting exported out of this file. The other key thing is that those variables (mongoose & Schema) are getting defined to the global object. This seems like a way to flag that these variables are going to be globals and this file doesn't export those via the module interface. I can't see any other reason to do this. – sujal Apr 25 '12 at 20:23

2 Answers2

15

My guess is the original author of that sample code is confused about module.exports vs exports. To use the exports object, you must add properties to it like this:

exports.size = 42;

If you re-assign the exports variable to a new object, you basically lose access to the global exports object that node.js provided for you. If you do this twice or three or N times, the effect is the same. It's useless. For example: mod_b.js

var realExports = exports;
realExports.height = 42;
var exports = {};
exports.weight = 43;

And in mod_a.js

var mod_b = require('./mod_b');
console.dir(mod_b);

Run node mod_a.js and you get:

{ height: 42 }

Notice height is there but weight is not. Now, what you can do is assign module.exports to be an object, and that is the object that will be returned when another module requires your module. So you will see things like.

var x = 10;
var y = 20;
module.exports = {x: x, y: y};

Which will do what you expect. Here's some informative articles on the details.

Node.js Module – exports vs module.exports

What is the purpose of NodeJS module.exports and how do you use it?

Mastering Node

Community
  • 1
  • 1
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
1

As an extension to @Peter-Lyons answer, your example is valid, your test case is incorrect.

Exporting variables like this is not recommended, but by doing that, you are exposing this variables into a global namespace.

e.g. test0.js

'use strict';

var assert = require('assert');
var test1 = require('./test1');

assert(globalVar1 === 123);
assert(globalVar2.a === 123);

test1.js -- mind the missing 'use strict';

exports = globalVar1 = 123;
exports = globalVar2 = {a:123};

Once again, it's valid, but not recommended.

Cheers.

Evan P
  • 1,767
  • 1
  • 20
  • 37