Summary:
We propose a backwards-compatible extension to the exports mechanism
of
Modules/1.1 that will make it easier to export individual pre-made
objects.
Background:
The system we are building occasionally contains individual objects
that
we wish to export. With the current system, exporting them is somewhat
ungainly.
For example, imagine that we were exporting a router for a dynamic
application:
// Example module "routes"
var userPage = require('pages/user'), Router =
require('classes/router');
var router = new Router();
router.route("/:username", userPage.profile);
router.route("/:username/friends", userPage.friends);
// ...and so on.
exports.instance = router;
All we really want to export here is the router itself, but the
current
system requires us to return it as a property of the exports object.
That means that consuming code has to do something like this:
var router = require('router').instance;
We believe that the consuming code would be more readable if the
.instance was not required:
var router = require('router'); // this is not how it works :(
Proposal:
Rather than having exports be a plain object, have it be a function
that
may or may not be called. If it is called, the first argument is to be
used as the exported value of the function. Otherwise, it is treated
as
a object, just as it currently is.
For example, our router example above currently exports the router
like
this:
exports.instance = router;
We propose an extension to the exports mechanism that would optionally
allow modules to do this instead:
exports(router);
Take the following imaginary implementation of Modules/1.1. Assume
that
"module" is a reference to a Module, and that we track the exports of
all of the modules in the exportsByModule object.
var exports = {};
module(exports);
exportsByModule[module.id] = exports;
This proposed change would change that implementation to something
along
these lines:
var exports = function(obj) {
// exports called as a function; use first argument as exports for
// this module
exportsByModule[module.id] = obj;
}
module(exports);
if (typeof(exportsByModule[module.id]) == 'undefined') {
// traditional behavior; copy properties that were added to exports
exportsByModule[module.id] = {};
for(var key in exports) {
if(exports.hasOwnProperty(key)) {
exportsByModule[module.id][key] = exports[key];
}
}
}
We believe that this change is useful and makes certain use cases more
readable, while remaining fully backwards compatible with Modules/1.1.