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.
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.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
.
Related Topics
JavaScript Syntax (0, Fn)(Args)
What Are Passive Event Listeners
Track Event in Google Analytics Upon Clicking Form Submit
How to Define Custom Sort Function in JavaScript
Adding a New Array Element to a JSON Object
Avoid Window Jump to Top When Clicking #-Links
Save JSON String to Client Pc (Using HTML5 API)
Download Textarea Contents as a File Using Only JavaScript (No Server-Side)
Open a New Tab with JavaScript But Stay on Current Tab
How to Set Preview of Video File, Selecting from Input Type='File'
Angular2:Render a Component Without Its Wrapping Tag
Get and Set a Single Cookie with Node.Js Http Server
Detecting Back Button/Hash Change in Url
How to Remove One Specific Selected File from Input File Control
Converting Any String into Camel Case
How to Apply CSS to the Elements Within an Iframe