4

I don't know what this pattern is called, if I did I would look it up directly.

Mainly, how does this work? (This code is taken from Express.js)

exports = module.exports = createApplication;

I have seen similar patterns before where there is this type of reference variable chain ex:

x = y = z

I understand exports vs module.exports but looking at the pattern above it makes me question on how it actually works.

I go by the general rule of thumb that 'module.exports' is the real deal, and 'exports' is its helper, more on this here

Is the module pattern like this (without altering module.exports)?

exports = module.exports = {};

ex:

exports.name = 'hello' 

results to

exports = module.exports = {name: 'hello'}

What happens when you change the reference on exports?

exports = {name: 'bob'}

Now when you add to exports, it will reference the `{name: 'bob'} and no longer have any ties with module.exports?

HelloWorld
  • 8,360
  • 9
  • 23
  • 41
  • I recently stepped through a NodeJS application (you might do this your self, try [Node Inspector](https://github.com/node-inspector/node-inspector) ) and noticed a function that has automagically been wrapped around each module. Its signature was `function(module, exports, /* two other */) { /* the actual module code */ }`. I suspect, `exports` is just a shorthand for `module.exports` as I came across both assignments. So, I don't think theres a difference which left hand side you're using and `exports = module.exports` is redundant. – try-catch-finally May 07 '14 at 05:36

1 Answers1

2

Your intuition is correct. I'll work from the bottom up:

The Node.js Wrapper

Before running any file, Node.js wraps the entire script in an immediately-invoked function expression (IIFE):

(function (exports, require, module, __filename, __dirname) {
    // ...script goes here...
});

This is how it introduces the module and exports variables into the scope; they're nothing more special than function arguments.

Using exports

The Node.js docs on module.exports and the exports alias are pretty helpful. To start out, module.exports and the exports variable both refer to the same empty object that was created by the module system.

If a module simply needs to export a plain old JavaScript object with some properties set, exports is all that's needed:

exports.get = function(key) {
    // ...
};

exports.set = function(key, value) {
    // ...
};

When code require()s this module, the result will look something like:

{
    get: [Function],
    set: [Function]
}

Replacing module.exports

However, Express exports a constructor function, createApplication, as the root value. To export the function itself, rather than just assigning it to a property on the exported object, it must first replace the exported object entirely:

module.exports = createApplication;

Now, exports hasn't been updated and still refers to the old object, whereas module.exports is a reference to createApplication. But if you keep reading, you'll notice that Express exports several other properties in addition to the constructor. While it would be sufficient to assign these to properties on the new value of module.exports, it is shorter to reassign exports so that it is again an alias to module.exports, then assign those properties on exports, which is equivalent to assigning them on module.exports.

Thus, these examples are functionally equivalent:

module.exports = createApplication;

function createApplication() {
    // ...
}

module.exports.application = proto;
module.exports.request = req;
module.exports.response = res;

But this one is less verbose:

exports = module.exports = createApplication;

function createApplication() {
    // ...
}

exports.application = proto;
exports.request = req;
exports.response = res;

Either way, the result is the same, a function named createApplication at the root with properties available on it:

{
    [Function: createApplication]
    application: [Object],
    request: [Object],
    response: [Object],
    // ...a few other properties...
}
Community
  • 1
  • 1
btmills
  • 3,514
  • 24
  • 20