Reputation: 1606
As I read through the some of the answers on another question on this topic:
I (guess) understand what exports and module.exports are and how they can be used!
What I don't understand is why do we need exports anyway since we can perfectly work things out with using only module.exports. Besides, If I conceive it good: exports has potential to create bugs.
For example:
// feature.js
function Person(name) {
this.name = name;
this.greet = function() {
console.log('Hi, my name is ' + this.name);
}
}
module.exports = Person;
// app.js
var Person = require(./feature);
var Aron = new Person('Aron');
Aron.greet(); // Hi, my name is Aron
You can simply break this working version with using exports:
exports = Person; // wont' work
exports.Person = Person; // still won't work (until you resolve it as new Person.Person('Aron') or ..require(..).Person) Which is not readable..
Why do we have exports anyway? Can someone explain to me the benefits of using exports instead of module.exports?
Thanks advance!
Upvotes: 2
Views: 101
Reputation: 707308
If you are just adding properties to module.exports
or to exports
, then you can modify either one and get the same result. This is because both module.exports
and exports
initially point to the exact same object. So, if you modify one, the other is pointing at the same object so the change will be seen in either one. exports
is apparently just provided as a typing shortcut so you don't have to refer to module.exports
.
So, this is perfectly safe:
exports.foo = 123;
Or
module.exports.foo = 123;
Both create exactly the same result and are both safe as they each just assign a property to the same object.
But, if you are creating and assigning a whole new exports object, then you MUST assign that object to module.exports
. Assigning it only to exports
will not do you any good.
The syntax:
exports = module.exports = {foo: 1};
Makes absolutely sure that no mistakes are made in this regard and is probably why it is recommended.
What I don't understand is why do we need
exports
anyway since we can perfectly work things out with using onlymodule.exports
.
As long as your code NEVER uses exports
, you can just use module.exports
and never worry about exports
. You do not NEED exports
. It was likely provided as a convenience, but as you have figured out that convenience can lead to bugs if misused.
Why do we have exports anyway? Can someone explain to me the benefits of using exports instead of module.exports?
exports
was probably just provided as a typing convenience. The only benefit to using exports
over module.exports
is a little less typing and perhaps a teeny performance difference as there is one less property lookup. Personally I just pretend exports
isn't there and I never use it. I logically think of module.exports
as the real location for exports so I just assign or modify there and there is never have a problem doing it that way.
Here's the longer explanation.
When a module is initialized, it is wrapped inside a function that looks like this:
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = '123;
});
This is where the definition of module
and exports
come from. By default, module.exports === exports
when this function is first executed and your module code starts to run. But, exports
is just a convenience here. The real exports are in module.exports. So, if you just do this:
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
exports = {foo: 123};
});
That ends up not doing anything because module.exports
will not be affected at all and that's where the real exports are. But, if you do this:
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
module.exports = {foo: 123};
});
Then, the real exports are indeed modified and your module will work properly, but as soon as you execute module.exports = {foo: 123};
, you've made module.exports
point to new object and it will now point at a different object than exports
points to. So, for total safety, some people recommend you do this:
(function (exports, require, module, __filename, __dirname) {
//contents from file1.js
exports = module.exports = {foo: 123};
});
Then, both exports
and module.exports
always point at the same object.
If you NEVER use exports
by itself, then you don't ever need to assign anything to it and you can just do this:
module.exports = {foo: 123};
And, there will be no issues at all. But, you have to make sure that no code actually uses just exports
if you've changed the object that module.exports
points to.
Upvotes: 6