Difference between exports and module.exports in Node.js
When you have large javascript file, you want to break that file into independent modules so that you can reuse each module in different files. Node.js follows CommonJS module system in which modules are imported using require
method available in global scope. For example, lets say you have two files, person.js
and main.js
. To import person.js
functionality into main.js
, you would do this
var Person = require('person');
Now you can use methods defined in person.js in main.js using Person variable. To be able to get the Person variable from person.js file, we should have return statement inside the person.js
file so that require
method assigns return value to the Person variable. person.js would look like this
'use strict'; module.exports = function(name, age) { return { get_name: function() {return name}, get_age: function() {return age} } }
And, main.js
would look like this
'use strict'; var Person = require('./person'); var person = new Person('Bibek', 25); console.log(person.get_name());
Running main.js
would give name of the person.
So far I showed you way of importing file into another file using module.exports
. But what if I replace module.exports
with exports
in above code? … this wont work. This is really confusing for beginner.
To illustrate why replacing module.exports
with exports
doesn’t work, let me revise your basic Javascript knowledge.
Consider following code snippet
'use strict'; // initialize two empty objects var object2 = {} var object1 = object2; // Mutate object1 object1.name = "object name"; // print name perperty for both objects console.log(object1.name); //outputs 'object name' console.log(object2.name); //outputs 'object name' // similary mutate object2 object2.name = "another name"; // again print name for both objects console.log(object1.name); //outputs 'another name' console.log(object2.name); //outputs 'another name' // assign object 1 values object1 = {name : "assigned name"} // print objects console.log(object1.name); //outputs 'assigned name' console.log(object2.name); //outputs 'another name' ????? // similary assgn object 2 value object2 = {name: "another assigned name"} // print objects console.log(object1.name); //outputs 'assigned name' console.log(object2.name); //outputs 'another assigned name' ?????
exports
and module.exports
. In above code, both object1
and object2
points to the same reference. If I change the contents of anyone of the objects, it will reflect in both but If I change the object itself it will not reflect. That means mutation will change all objects having same reference but assignment will change only one objectTo further illustrate this, lets consider following example 1
exports = function() { console.log('with exports only'); }
when we assign function to exports. Following will be the result of exports
and module.exports
exports = [function], module.exports = {}
Since module.exports
will be returned, this will return empty object. So this doesn’t work.
Now, consider example 2
exports.a = function () { console.log('exports with mutation'); }
When we mutate exports
, following will be the result of exports
and module.exports
exports = {a: [function]}, module.exports = {a: [funciton]}
This will return non-empty object. So thi
s works
module.exports = function() { console.log('with module.exports only'); }
When we assign function to module.exports
, following will be the contents of exports
and
module.exports
.
exports = {}, module.exports = [funciton]
This will return non-empty object. So this also works.
Great post and I have bookmarked as reference.
Really great article . Thankyou for explaining it with an example and making the concept more clear .
Thank you for this article . You have cleared all my doubts ! I have bookmarked this site for reference
Nice Content, thank you for the information