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 purpose of Node.js module.exports and how do you use it?
module.exports
is the object that's actually returned as the result of a require
call.
The exports
variable is initially set to that same object (i.e. it's a shorthand "alias"), so in the module code you would usually write something like this:
let myFunc1 = function() { ... };
let myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;
to export (or "expose") the internally scoped functions myFunc1
and myFunc2
.
And in the calling code you would use:
const m = require('./mymodule');
m.myFunc1();
where the last line shows how the result of require
is (usually) just a plain object whose properties may be accessed.
NB: if you overwrite exports
then it will no longer refer to module.exports
. So if you wish to assign a new object (or a function reference) to exports
then you should also assign that new object to module.exports
It's worth noting that the name added to the exports
object does not have to be the same as the module's internally scoped name for the value that you're adding, so you could have:
let myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required
followed by:
const m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
How does exports object reference module.exports in Node.js?
CommonJS modules are actually pretty simple: you take all the code in a file, and just wrap it in a function. Execute the function, and return the value of module.exports
after execution to the caller.
You can see this function's header in the node.js source code:
const wrapper = [
'(function (exports, require, module, __filename, __dirname) { ',
'\n});'
];
The wrapper is applied to the code in the require
'd file and then called like this:
const exports = this.exports;
const thisValue = exports;
const module = this;
if (requireDepth === 0) statCache = new Map();
if (inspectorWrapper) {
result = inspectorWrapper(compiledWrapper, thisValue, exports,
require, module, filename, dirname);
} else {
result = compiledWrapper.call(thisValue, exports, require, module,
filename, dirname);
}
As you can see it's pretty straightforward. const exports = this.exports
, and then exports
is passed as an argument to the wrapper function - thus they initially point to the same value, but if you reassign either then they no longer do.
Why we use exports in nodejs?
TL;DR
You can use:
exports.x = 1;
exports.y = 2;
exports.z = 3;
as a shorter way of writing:
module.exports.x = 1;
module.exports.y = 2;
module.exports.z = 3;
The only advantage is less typing.
But you have to write:
module.exports = {
x: 1,
y: 2,
z: 3
};
as this will not work:
exports = {
x: 1,
y: 2,
z: 3
};
because it wouldn't change the module.exports
and it's module.exports
that actually gets exported.
Explanation
Your module gets wrapped in an implicit closure that gets some variables passed as parameters. One of those variables is called exports
that is an empty object and another one is called module
and it includes exports
as one of its properties:
module.exports === exports
When you write:
exports.x = 10;
then you change the property of the provided object (the object is still the same object, but it is mutated) and everything is fine. The value x
is available as both exports.x
and module.exports.x
.
But if you write:
exports = {x: 10};
then you assign a new object to exports
while the module.exports
is still pointing to the original (empty) object. That way you have exports.x
set correctly but you don't have module.exports.x
set as well, because now:
module.exports !== exports
If you want to make a new object instead of using the empty one that you got in exports
then you have to assign it to module.exports
:
module.exports = {x: 10};
Now module.exports
and exports
are different as well:
module.exports !== exports
But it's module.exports
that's actually exported so everything is fine.
After assigning a new object to module.exports
you could assign it to exports
as well:
module.exports = {x: 10};
exports = module.exports;
or do it the other way around:
exports = {x: 10};
module.exports = exports;
so you could still use the shortcut of assigning new properties with:
exports.y = 20;
but I haven't seen that in practice.
Real examples
Exporting some functions (public) but not others (private).
Let's say you have those functions:
function private1() {
// ...
}
function private2() {
// ...
}
function public1() {
// ...
}
function public2() {
// ...
}
You have few options to export two public functions:
This works
module.exports.public1 = public1;
module.exports.public2 = public2;
or:
exports.public1 = public1;
exports.public2 = public2;
or:
module.exports = {
public1: public1,
public2: public2
};
or:
module.exports = {
public1,
public2
};
This doesn't work
exports = {
public1: public1,
public2: public2
};
or:
exports = {
public1,
public2
};
Summary
In other words, exports
is just for convenience so that you don't have to write module.exports
every time, but it doesn't work for cases when you want to export a different object than the one provided to you originally. In that case you need to set the module.exports
to that new object.
See also
See also this answer:
- What is the difference between module.export and export
Node.js module.exports a function with input
You can use promises to handle the async functions
Try Changing your module.exports to return a promise function
const crypto = require("crypto");
module.exports = function (x, y) {
return new Promise(function (resolve, reject) {
var addition;
crypto.randomBytes(5, function (err, data) {
addition = data.toString("hex");
if (!addition) reject("Error occured");
resolve(x + y + addition);
})
});
};
You can then call the promise function using the promise chain
let e = require("./encryption.js");
e(1, 2).then((res) => {
console.log(res);
}).catch((e) => console.log(e));
Suggest you to read Promise documentation
For node version > 8, you can use simple async/await
without promise chain.You have to wrap your api inside a promise using utils.promisify
(added in node 8) and your function should use the keyword async
.Errors can be handled using try
catch
const util = require('util');
const crypto = require("crypto");
const rand = util.promisify(crypto.randomBytes);
async function getRand(x, y){
try{
let result = await rand(5);
console.log(x + y + result);
}
catch(ex){
console.log(ex);
}
}
console.log(getRand(2,3));
where do module.exports export your function and what is the use of it when we still use require to import the code into your module
(#1 and #4 don't need answers, so I've left them off.)
2) But i want to know why we can see a log which we have written in notes.js without using module.exports statment.
With Node.js's style of modules (which is a flavor of CommonJS), a module is loaded and executed when it's first require
d. Your console.log
is in the module's code, so when you require
it (the first time), that code gets run.
why can't we use require statment and store total code and call the function from that varable as we do for a instance of a class
You can, if that's what you want to do:
exports = {
// code here as object properties
addNote: () => {
console.log('addNote');
return 'New note';
}
};
and
const mod = require("./notes.js");
mode.addNote();
3)More preciously where do module.export export your code (i mean to which directrey )
To the module cache in memory.
meaning of module.exports= function in node.js
It works exactly the same as the first one does, only that it exports a function instead of an object.
The module that imports the module can then call that function:
var dummy = require('./dummy.js');
dummy();
any idea how can i export variables from module defined like this..?
Since functions are just objects, you can also assign properties to it:
module.exports = function(passport,config, mongoose) {}
module.exports.user = 'rally';
However I'd argue that this is less expected if a module directly exports a function. You are probably better off exporting the function as its own export:
exports.login = function(passport,config, mongoose) {}
exports.user = 'rally';
does module.exports simply binds function to an object?
Two are almost same.
when you use this.
module.exports = {func1,func2,func3}
you have to import like this.
const {funct1,funct2,funct3} = require('./path/to/file');
if you use like this
module.exports.func4= func1;
module.exports.func5 = func2 ;
module.exports.func6 = func3;
you have to import like this:
const {funct4,funct5,funct6} = require('./path/to/file');
Both are same but when you use first method you have to use the same name wherever you call your function.
But with second method you can use different names.
Hope you get the idea!
How to use module exports correctly in my local app
There are several ways to achieve what you wish. One simple but effective solution is to add an attribute to the global object. This has to be done in your main (entry) js file, before any require
statements:
(Paths below are built assuming your entry js file is in the app
folder)
global.__runCmdPath = __dirname + '/common/cmd/run-cmd';
Then, in any other module from which you would like to require runCmd
you could simply:
const runCmd = require(__runCmdPath);
You could even set, as attribute of the global object, the base directory of the scripts containing the functions you'd like to export, and then just append the single script-name, like:
const runCmd = require(__scriptsDir + '/run-cmd');
const runCmd2 = require(__scriptsDir + '/run-cmd2');
Another strategy would be to add the scripts folder to the NODE_PATH
environmental variable, with the following command for UNIX:
export NODE_PATH=./common/cmd
and for Windows:
set NODE_PATH=./common/cmd
Then, you may command node app.js
and this way, you will simply be able to require('run-cmd')
everywhere. This will work as long as you remember to re-set the variable everytime you start a new shell session.
For what regards TypeError: runCmd is not a function.
, this will continue to occur if you try to call runCmd directly, from where you have required it. This is because require()
returns an exports object, and your exported methods all belong to this object.
If you would like to call the runCmd method you exported, in this case, you'll have to do it this way:
runCmd.runCmd('vcgencmd measure_temp', function(result) {
console.log("Result we are prepping to send: " + result);
res.json({result: result});
});
Thus, you might want to re-name the constant containing your exports object, or the exported name of the runCmd function, to whatever suits you best.
Related Topics
What Is the !! (Not Not) Operator in JavaScript
Add a Property to a JavaScript Object Using a Variable as the Name
Setting "Checked" For a Checkbox With Jquery
Short Circuit Array.Foreach Like Calling Break
Convert Date to Another Timezone in JavaScript
How to Completely Uninstall Node.Js, and Reinstall from Beginning (Mac Os X)
How to Use Formdata For Ajax File Upload
Is JavaScript Guaranteed to Be Single-Threaded
Chrome/Firefox Console.Log Always Appends a Line Saying 'Undefined'
Executing ≪Script≫ Elements Inserted With .Innerhtml
How to Export JavaScript Array Info to CSV (On Client Side)
Difference Between Null and Undefined in JavaScript
How to Check If a String "Startswith" Another String
How to Create an Accurate Timer in JavaScript
In JavaScript, Does It Make a Difference If I Call a Function With Parentheses
How to Set Object Property (Of Object Property Of..) Given Its String Name in JavaScript
How to Make the Window Full Screen With JavaScript (Stretching All Over the Screen)