module.exports vs exports in Node.js
Setting module.exports
allows the database_module
function to be called like a function when required
. Simply setting exports
wouldn't allow the function to be
exported because node exports the object module.exports
references. The following code wouldn't allow the user to call the function.
module.js
The following won't work.
exports = nano = function database_module(cfg) {return;}
The following will work if module.exports
is set.
module.exports = exports = nano = function database_module(cfg) {return;}
console
var func = require('./module.js');
// the following line will **work** with module.exports
func();
Basically node.js doesn't export the object that exports
currently references, but exports the properties of what exports
originally references. Although Node.js does export the object module.exports
references, allowing you to call it like a function.
2nd least important reason
They set both module.exports
and exports
to ensure exports
isn't referencing the prior exported object. By setting both you use exports
as a shorthand and avoid potential bugs later on down the road.
Using exports.prop = true
instead of module.exports.prop = true
saves characters and avoids confusion.
What is the difference between module.exports and exports.module in java script
module.exports
is the property used to export values from a CommonJS module.
exports
is a shorthand for module.exports
.
exports.module
is the same as module.exports.module
which creates an value named module
on the exported object.
So if you have:
module.exports = Product;
Then you would match it with:
const Product = require('./myModule');
But if you have:
exports.module = Product;
Then you would:
const myModule = require('./myModule');
const Product = myModule.module;
exports.module
is, basically, a mistake and makes code confusing. Don't do that.
module.exports vs. export default in Node.js and ES6
The issue is with
- how ES6 modules are emulated in CommonJS
- how you import the module
ES6 to CommonJS
At the time of writing this, no environment supports ES6 modules natively. When using them in Node.js you need to use something like Babel to convert the modules to CommonJS. But how exactly does that happen?
Many people consider module.exports = ...
to be equivalent to export default ...
and exports.foo ...
to be equivalent to export const foo = ...
. That's not quite true though, or at least not how Babel does it.
ES6 default
exports are actually also named exports, except that default
is a "reserved" name and there is special syntax support for it. Lets have a look how Babel compiles named and default exports:
// input
export const foo = 42;
export default 21;
// output
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var foo = exports.foo = 42;
exports.default = 21;
Here we can see that the default export becomes a property on the exports
object, just like foo
.
Import the module
We can import the module in two ways: Either using CommonJS or using ES6 import
syntax.
Your issue: I believe you are doing something like:
var bar = require('./input');
new bar();
expecting that bar
is assigned the value of the default export. But as we can see in the example above, the default export is assigned to the default
property!
So in order to access the default export we actually have to do
var bar = require('./input').default;
If we use ES6 module syntax, namely
import bar from './input';
console.log(bar);
Babel will transform it to
'use strict';
var _input = require('./input');
var _input2 = _interopRequireDefault(_input);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_input2.default);
You can see that every access to bar
is converted to access .default
.
Difference between module.exports and exports in the CommonJs Module System
module
is a plain JavaScript object with an exports
property. exports
is a plain JavaScript variable that happens to be set to module.exports
.
At the end of your file, node.js will basically 'return' module.exports
to the require
function. A simplified way to view a JS file in Node could be this:
var module = { exports: {} };
var exports = module.exports;
// your code
return module.exports;
If you set a property on exports
, like exports.a = 9;
, that will set module.exports.a
as well because objects are passed around as references in JavaScript, which means that if you set multiple variables to the same object, they are all the same object; so then exports
and module.exports
are the same object.
But if you set exports
to something new, it will no longer be set to module.exports
, so exports
and module.exports
are no longer the same object.
What is the difference between module.export and export
First of all it's exports
and module.exports
and not export
and module.export
(there is also an export
keyword in JavaScript but it is not supported in Node yet).
Every Node module is wrapped with this function:
(function (exports, require, module, __filename, __dirname) {
// Your module code actually lives in here
});
See: https://nodejs.org/api/modules.html#modules_the_module_wrapper
Your module doesn't return the exported object from that functions as some people think. It can only pass data to the caller by adding properties to the arguments provided.
module.exports
and exports
are initially the same object - but it is module.exports
that is actually exported if they end up to be not the same object.
It means that this will work the same:
module.exports.x = 1;
# or:
exports.x = 1;
because it changes the property of the same object.
But this will not be the same:
module.exports = {x: 1};
as this:
exports = {x: 1};
The last one will not export the x
because it will substitute the object in exports
(that was originally the same object as module.exports
) while leaving the default empty object in module.exports
to be actually exported.
The module.exports = {x: 1};
also substitutes a new object but it puts it where it needs to be to actually get exported. Note that this instruction changes the property
of the module
object, which can be seen by the caller after the implicit function that your module is wrapped in returns.
Now this would work:
exports = {x: 1};
module.exports = exports;
because it substitutes the object in exports
with a new one but it also puts it into module.exports
.
Remember that it is always module.exports
that matters at the end if you didn't substitute one of them with a new object then you can use them interchangeably when setting their attributes:
exports.x = 1;
module.exports.y = 2;
For more info see this answer:
- Why we use exports in nodejs?
Related Topics
Jquery Validate Plugin - How to Create a Simple Custom Rule
What's the Difference Between Event.Stoppropagation and Event.Preventdefault
How to Post Urlencoded Form Data With $Http Without Jquery
Surprised That Global Variable Has Undefined Value in JavaScript
Chrome: Timeouts/Interval Suspended in Background Tabs
Count the Number of Occurrences of a Character in a String in JavaScript
Take a Screenshot of a Webpage With JavaScript
Use of .Apply() With 'New' Operator. Is This Possible
How to Count String Occurrence in String
How Does This JavaScript/Jquery Syntax Work: (Function( Window, Undefined ) { })(Window)
Set Keyboard Caret Position in HTML Textbox
Chained Promises Not Passing on Rejection
Read CSS Property of an Element Using JavaScript
Toggle Visibility Property of Div