Closed GoogleCodeExporter closed 8 years ago
It seems that the module system is retaining a pointer to the initial value of
exports rather than the symbol. Although this behaviour is hinted at in the
commonjs wiki it is counter-intuitive and awkward (and also time consuming to
debug when it doesn't work.)
Original comment by andy.bis...@gmail.com
on 7 Jun 2012 at 3:10
Exports are a readonly object; this is a feature, not a bug.
Please see the whole thread at
https://groups.google.com/forum/?fromgroups#!topic/commonjs/EcbyXEazg3s for
more discussion and argumentation.
TL;DR: as long as commonjs does not standardize exports as mutable, this
implementation will remain commonjs-compliant. Assigning to exports is
generally VERY bad practice with respect to code maintainability; it also
introduces circular dependency issues and breaks middleware:
var requireGroupOfModules = function(modules) {
var result = [];
for (var i=0;i<modules.length;i++) {
result = result.concat(require(modules[i]));
}
return result;
}
This function would not be possible if exports were mutable.
Finally, it is a good and very sane practice that a function returns only ONE
datatype (an object, in the case of "require"). It makes the code much more
deterministic and error-proof, even if the language itself is dynamic.
If you show me what do you consider "awkward" and "counter-intuitive", I might
be able to provide some more assistance. You can also visit #commonjs at
freenode; people there will be sure open to share their opinions and explain
motivations behind this.
Original comment by ondrej.zara
on 7 Jun 2012 at 4:17
To be fair, most of that discussion is arguing for something different and
ill-advised. There is no issue in defining the required return type (in
this case an object) as this is a reasonable expectation. What is
unreasonable (and breaks the rule of least surprise) is introducing
immutable symbols by decree. JavaScript symbols are mutable even when they
shouldn't be (undefined!) and this is what the user expects. Also, I
cannot see any way in which the mutability or otherwise of a symbol in an
included module would affect its use in the including module. How exactly
would the code presented fail? I can think of horrible abuses of this rule
(var thing = exports; exports = {}; ....... exports.fred = fred) but I
would not normally consider the potential for such abuse to be a good
argument either way.
Having said that, you are compliant with the letter of the commonjs spec so
I guess that you are the wrong person to argue the case with :)
Original comment by andy.bis...@gmail.com
on 7 Jun 2012 at 5:25
Well, if you agree that require() should always return a plain object, the
problem with middleware vanishes.
However, circular dependency issues are still present:
a.js:
require("b");
b.js:
require("a");
This situation works as expected when exports are non-mutable; does not work
otherwise.
As for the mutability of JS objects - think of "exports" as of an function
argument. In fact, it *is* a function argument: in v8cgi, your code is always
wrapped in a
(function(require, exports, module){ .... })
wrapper. Assigning to exports just shadows the passed value; that's how
function arguments behave.
Original comment by ondrej.zara
on 8 Jun 2012 at 7:56
Original issue reported on code.google.com by
andy.bis...@gmail.com
on 7 Jun 2012 at 3:00