779

I've found the following contract in a Node.js module:

module.exports = exports = nano = function database_module(cfg) {...}

I wonder whats the different between module.exports and exports and why both are used here.

Yves M.
  • 26,153
  • 20
  • 93
  • 125
Andreas Köberle
  • 88,409
  • 51
  • 246
  • 277
  • 5
    For posterity: http://nodejs.org/docs/latest/api/modules.html#module.exports – orftz Feb 08 '12 at 16:57
  • 91
    Great resource: http://www.hacksparrow.com/node-js-exports-vs-module-exports.html ^_^ – Naftali aka Neal Dec 10 '12 at 15:12
  • 7
    Updated 'for posterity' link: http://nodejs.org/docs/latest/api/modules.html#modules_module_exports – Zeke Mar 20 '13 at 20:55
  • 8
    It's all about references. Think of exports like a local variable object pointing to module.exports. If you overrite the value of exports, then you lose the reference to module.exports, and module.exports is what you expose as a public interface. – Gabriel Llamas Jan 06 '15 at 12:00
  • 15
    **Quick Summary:** both `exports` and `module.exports` point to the same object, unless you reassign one. And in the end `module.exports` is returned. So if you reassigned `exports` to a function then dont expect a function since it isn't going to be returned. However if you had assigned function like this `exports.func = function...` then resulting thing would have func property with function as a value. Because you added the property to the object that `exports` was pointing to .. – Muhammad Umer Jun 23 '15 at 19:51
  • 1
    Can't understand why provide both `module.exports` and `exports`. Why not just provide `module.exports` to avoid such confusion? – Freewind Jun 19 '16 at 13:01
  • @Neal, hacksparrow - "if you want your module to be of a specific object type, use module.exports; if you want your module to be a typical module instance, use exports." huh, what, why?. – TarranJones Aug 02 '16 at 09:07
  • Here is my 2 minute article on this topic (written in Node v6 and ES2015): https://medium.com/@lazlojuly/node-js-module-exports-vs-exports-ec7e254d63ac – lazlojuly Sep 07 '16 at 14:33
  • Well, I have read every single reply here, and I still have no clue what the difference between the two is, when and how to use one vs. the other, or why there are two. – John Little Jun 27 '17 at 13:36
  • `module.exports` is not a function... Why is that? – Post Self Oct 03 '17 at 19:29
  • @JohnLittle check out my new answer re: why use both https://stackoverflow.com/a/50162465/4722345 – JBallin May 03 '18 at 19:21
  • @TarranJones I've added my own words for clarity ([]): If you want your module to be of a specific object type [(such as a function/string/array)], use module.exports; if you want your module to be a typical module instance, [you should] use exports [, exclusively, to be concise]. See my answer for examples etc. https://stackoverflow.com/a/50162465/4722345 – JBallin May 03 '18 at 19:27
  • @GabrielLlamas, "It's all about references" summerizes my struggles with learning JavaScript... But your comment is straight to the point, `module.exports` and `exports` are references to one object, reassigning to something else would change the reference. – Moad Ennagi Jun 13 '19 at 08:44

24 Answers24

563

Even though question has been answered and accepted long ago, i just want to share my 2 cents:

You can imagine that at the very beginning of your file there is something like (just for explanation):

var module = new Module(...);
var exports = module.exports;

enter image description here

So whatever you do just keep in mind that module.exports and NOT exports will be returned from your module when you're requiring that module from somewhere else.

So when you do something like:

exports.a = function() {
    console.log("a");
}
exports.b = function() {
    console.log("b");
}

You are adding 2 functions a and b to the object to which module.exports points, so the typeof the returning result will be an object : { a: [Function], b: [Function] }

Of course, this is the same result you will get if you are using module.exports in this example instead of exports.

This is the case where you want your module.exports to behave like a container of exported values. Whereas, if you only want to export a constructor function then there is something you should know about using module.exports or exports;(Remember again that module.exports will be returned when you require something, not export).

module.exports = function Something() {
    console.log('bla bla');
}

Now typeof returning result is 'function' and you can require it and immediately invoke like:
var x = require('./file1.js')(); because you overwrite the returning result to be a function.

However, using exports you can't use something like:

exports = function Something() {
    console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function

Because with exports, the reference doesn't point anymore to the object where module.exports points, so there is not a relationship between exports and module.exports anymore. In this case module.exports still points to the empty object {} which will be returned.

The accepted answer from another topic should also help: Does JavaScript pass by reference?

riQQ
  • 4,188
  • 4
  • 19
  • 33
Srle
  • 9,554
  • 7
  • 30
  • 58
  • 2
    Nice explanation but I still don't understand how you can completely omit `module.exports` from a module, for example in this `npm` package: https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js – CodyBugstein Feb 09 '15 at 07:46
  • 4
    @Imray the explanation is here: [Does JavaScript pass by reference?](http://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference) `exports.a = function(){}; works, exports = function(){} doesn't work` – cirpo Jun 12 '15 at 19:00
  • 40
    oooo finally this answer explains it. Basically export refers to an object to which you can add properties but if you **reassign** it to function then you are no long attach a property to that original object. Now export refer to function while module.exports is still pointing to that object and since it's what's returned. You can say export has been basically garbage collected. – Muhammad Umer Jun 23 '15 at 19:48
  • 7
    So then, what's the point of using `exports`? Why not just always use `module.exports` if it's just a variable reassignment? Seems confusing to me. – jedd.ahyoung Jul 04 '15 at 16:30
  • 2
    @jedd.ahyoung It is less cumbersome to write `exports.something` instead of `module.exports.something` – Srle Jul 04 '15 at 17:08
  • 1
    @jedd.ahyoung by adding properties to `exports` you are effectively ensuring that you are returning a "typical" module export *object*. In contrast, by using `module.exports` you can return any value you want (primitive, array, function) and not just an object (which is the format most people expect). So `module.exports` offers more power but can also be used to have your module export atypical values (like a primitive). In contrast `exports` is more limiting but safer (so long as you simply add properties to it and don't reassign it). – Marcus Junius Brutus Mar 24 '16 at 10:51
  • 1
    @Srle - Thank you for explaining what's actually going on, versus just describing the behavior (which just leads to more behavior questions). For people who know JS, informing us that the args are set up like `var module = new Module();` and `var exports = module.exports;` completely explains what's going on. – jeffwtribble Sep 30 '16 at 17:46
  • 1
    Thank you so much for this explanation. I don't even know why the answer above is accepted barely explains anything... –  Aug 08 '17 at 03:07
  • 1
    This answer clear up things for people who didn't understand other answers. Started saying from the scratch. – Asim K T Oct 10 '17 at 06:51
  • @CodyBugstein - You can omit `module.exports` because `exports` is a reserved variable that is implicitly declared by NodeJS runtime which automatically references the value of `module.exports`, as per docs: https://nodejs.org/api/modules.html#modules_exports – ElectroBuddha Mar 14 '18 at 11:04
  • 1
    For me, this was the answer that clicked. Thumbs up for the concise explanation. I recommend everyone to create a node project and constantly log the objects `exports` and `module.exports` to see its behavior. – 0xFED5550 Feb 14 '19 at 19:22
  • the best clear answer ! thank you a lot . – sohaieb azaiez Jan 28 '21 at 10:58
  • Webpack5 introduces some changes in library behaviour related to these export settings: https://hinty.io/devforth/fix-webpack-imported-module-is-not-a-function-for-webpack5/ – Ivan Borshchov Feb 14 '21 at 20:46
443

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.

Community
  • 1
  • 1
Lime
  • 12,724
  • 9
  • 48
  • 84
  • 8
    @ajostergaard: It just happens to be the name of the [library](https://github.com/dscape/nano/blob/master/nano.js) the OP's example was taken from. In the module, it allows the author to write things like `nano.version = '3.3'` instead of `module.exports.version = '3.3'`, which reads a little more clearly. (Note that `nano` is a local variable, [declared a little before the module exports are set](https://github.com/dscape/nano/blob/3.3.7/nano.js#L17-45).) – josh3736 Jan 14 '13 at 20:19
  • 3
    @lime - thanks - I'm glad it's largely irrelevant because if it wasn't it would mean I'd completely misunderstood everything. :-| :) – ostergaard Jan 14 '13 at 23:18
  • Hey Lime, this is a pretty old answer but I hope you can clarify something. If I were to set `module.exports` but *not* `exports`, would my code still work? Thanks for any help! – Asad Saeeduddin Feb 21 '13 at 00:42
  • 1
    @Asad Yes the function will export properly provided you set `module.exports` – Lime Feb 21 '13 at 23:19
  • @Liam thanks for the valuable answer. few more queries - at the entry of server.js, what is expected to be the values of module.exports and exports? is module.exports expected to be null and exports set to an empty object? Is this legacy or there is some valid use case to point exports and module.exports to two different object ever? – Sushil May 07 '13 at 06:45
  • @Sushi I wouldn't be surprised if the output changes based on the system. But most likely they don't. I would just run `console.log(exports)` and see what the default values are for your system. This isn't legacy entirely, basically they started with `exports` but they realized do to efficiency reasons that if they wanted to export an entire object (for example a function) that it would be best to create a property on already existing object namely `module.exports`. So basically to export a fun run `module.exports = function(){}` otherwise you can freely attach properties to the `exports` – Lime May 11 '13 at 04:43
  • I have no idea why they don't apply `set` `Proxy` for `exports`. – Константин Ван Oct 15 '17 at 16:16
214

Basically the answer lies in what really happens when a module is required via require statement. Assuming this is the first time the module is being required.

For example:

var x = require('file1.js');

contents of file1.js:

module.exports = '123';

When the above statement is executed, a Module object is created. Its constructor function is:

function Module(id, parent) {
    this.id = id;
    this.exports = {};
    this.parent = parent;
    if (parent && parent.children) {
        parent.children.push(this);
    }

    this.filename = null;
    this.loaded = false;
    this.children = [];
}

As you see each module object has a property with name exports. This is what is eventually returned as part of require.

Next step of require is to wrap the contents of file1.js into an anonymous function like below:

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
});

And this anonymous function is invoked the following way, module here refers to the Module Object created earlier.

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
}) (module.exports,require, module, "path_to_file1.js","directory of the file1.js");

As we can see inside the function, exports formal argument refers to module.exports. In essence it's a convenience provided to the module programmer.

However this convenience need to be exercised with care. In any case if trying to assign a new object to exports ensure we do it this way.

exports = module.exports = {};

If we do it following way wrong way, module.exports will still be pointing to the object created as part of module instance.

exports = {};

As as result adding anything to the above exports object will have no effect to module.exports object and nothing will be exported or returned as part of require.

caesarsol
  • 1,661
  • 1
  • 15
  • 19
Chandu
  • 4,371
  • 2
  • 15
  • 12
  • 9
    Lost me here `exports = module.exports = {};` – Giant Elk Apr 03 '15 at 03:02
  • 2
    I think this should be the best answer, it explains why `func()` fails in @William's answer! – turtledove Jul 17 '15 at 02:38
  • 3
    I don't see any advantage to add `exports = module.exports = app;` at the last line of the code. It seems like the `module.exports` will get exported and we will never use `exports`, because again it's at the last line of the code. So, why don't we just simply add `module.exports = app;` – lvarayut Dec 15 '15 at 04:19
90

Initially,module.exports=exports , and the require function returns the object module.exports refers to.

if we add property to the object, say exports.a=1, then module.exports and exports still refer to the same object. So if we call require and assign the module to a variable, then the variable has a property a and its value is 1;

But if we override one of them, for example, exports=function(){}, then they are different now: exports refers to a new object and module.exports refer to the original object. And if we require the file, it will not return the new object, since module.exports is not refer to the new object.

For me, i will keep adding new property, or override both of them to a new object. Just override one is not right. And keep in mind that module.exports is the real boss.

mic4ael
  • 6,326
  • 3
  • 28
  • 40
cameron
  • 2,666
  • 2
  • 19
  • 33
  • 3
    Yeah, this is actually the real answer. It's concise and clear. Others may be right but full of fancy terms and not focus exactly on the answer for this question. – Khoa Mar 01 '18 at 02:46
  • This is by far the clearest answer! In case you want to bookmark it, this is the precise link: https://stackoverflow.com/questions/7137397/module-exports-vs-exports-in-node-js/18178696#18178696 – lkbaerenfaenger Jun 06 '19 at 13:58
67

exports and module.exports are the same unless you reassign exports within your module.

The easiest way to think about it, is to think that this line is implicitly at the top of every module.

var exports = module.exports = {};

If, within your module, you reassign exports, then you reassign it within your module and it no longer equals module.exports. This is why, if you want to export a function, you must do:

module.exports = function() { ... }

If you simply assigned your function() { ... } to exports, you would be reassigning exports to no longer point to module.exports.

If you don't want to refer to your function by module.exports every time, you can do:

module.exports = exports = function() { ... }

Notice that module.exports is the left most argument.

Attaching properties to exports is not the same since you are not reassigning it. That is why this works

exports.foo = function() { ... }
dustin.schultz
  • 10,886
  • 6
  • 49
  • 59
30

JavaScript passes objects by copy of a reference

It's a subtle difference to do with the way objects are passed by reference in JavaScript.

exports and module.exports both point to the same object. exports is a variable and module.exports is an attribute of the module object.

Say I write something like this:

exports = {a:1};
module.exports = {b:12};

exports and module.exports now point to different objects. Modifying exports no longer modifies module.exports.

When the import function inspects module.exports it gets {b:12}

superluminary
  • 38,944
  • 21
  • 142
  • 143
14

I just make some test, it turns out that, inside nodejs's module code, it should something like this:

var module.exports = {};
var exports = module.exports;

so:

1:

exports = function(){}; // this will not work! as it make the exports to some other pointer
module.exports = function(){}; // it works! cause finally nodejs make the module.exports to export.

2:

exports.abc = function(){}; // works!
exports.efg = function(){}; // works!

3: but, while in this case

module.exports = function(){}; // from now on we have to using module.exports to attach more stuff to exports.
module.exports.a = 'value a'; // works
exports.b = 'value b'; // the b will nerver be seen cause of the first line of code we have do it before (or later)
Lyman Lai
  • 181
  • 1
  • 4
  • Lyman, so `module.exports` is sort of the 'real-deal' that node goes off of but at some point you'll need to add all your `exports` to `module.exports` unless you're using a `exports.namespace` (case 2 above), which in that case seems to be like Node ran a `extends(module.exports, exports);` adding all 'namespaces' of `exports` to the `module.exports` object? In other words, if you're using `exports` then you probably want to be setting properties on it? – Cody Mar 24 '14 at 22:04
12

Here is a good description written about node modules in node.js in action book from Manning publication.
What ultimately gets exported in your application is module.exports.
exports
is set up simply as a global reference to module.exports , which initially is defined as an empty object that you can add properties to. So exports.myFunc is just shorthand for module.exports.myFunc.

As a result, if exports is set to anything else, it breaks the reference between module.exports and exports . Because module.exports is what really gets exported, exports will no longer work as expected—it doesn’t reference module .exports anymore. If you want to maintain that link, you can make module.exports reference exports again as follows:

module.exports = exports = db;
Salar
  • 4,843
  • 4
  • 36
  • 62
8

I went through some tests and I think this may shed some light on the subject...

app.js:

var ...
  , routes = require('./routes')
  ...;
...
console.log('@routes', routes);
...

versions of /routes/index.js:

exports = function fn(){}; // outputs "@routes {}"

exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

module.exports = function fn(){};  // outputs "@routes function fn(){}"

module.exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

I even added new files:

./routes/index.js:

module.exports = require('./not-index.js');
module.exports = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

We get the output "@routes {}"


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

We get the output "@routes { fn: {}, user: {} }"


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.user = function user(){};

We get the output "@routes { user: [Function: user] }" If we change user.js to { ThisLoadedLast: [Function: ThisLoadedLast] }, we get the output "@routes { ThisLoadedLast: [Function: ThisLoadedLast] }".


But if we modify ./routes/index.js...

./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.ThisLoadedLast = function ThisLoadedLast(){};

... we get "@routes { fn: { fn: [Function: fn] }, ThisLoadedLast: { ThisLoadedLast: [Function: ThisLoadedLast] } }"

So I would suggest always use module.exports in your module definitions.

I don't completely understand what's going on internally with Node, but please comment if you can make more sense of this as I'm sure it helps.

-- Happy coding

Cody
  • 8,913
  • 4
  • 55
  • 42
  • I think they are unnecessarily complicated and confusing. It should be transparent and intuitive. – ngungo Apr 27 '14 at 01:11
  • I agree. It may be useful for namespacing is some circumstances, but is generally not going to make or break anything. – Cody Apr 28 '14 at 01:52
5

To understand the differences, you have to first understand what Node.js does to every module during runtime. Node.js creates a wrapper function for every module:

 (function(exports, require, module, __filename, __dirname) {

 })()

Notice the first param exports is an empty object, and the third param module is an object with many properties, and one of the properties is named exports. This is what exports comes from and what module.exports comes from. The former one is a variable object, and the latter one is a property of module object.

Within the module, Node.js automatically does this thing at the beginning: module.exports = exports, and ultimately returns module.exports.

So you can see that if you reassign some value to exports, it won't have any effect to module.exports. (Simply because exports points to another new object, but module.exports still holds the old exports)

let exports = {};
const module = {};
module.exports = exports;

exports = { a: 1 }
console.log(module.exports) // {}

But if you updates properties of exports, it will surely have effect on module.exports. Because they both point to the same object.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports.b = 2;
console.log(module.exports) // { a: 1, b: 2 }

Also notice that if you reassign another value to module.exports, then it seems meaningless for exports updates. Every updates on exports is ignored because module.exports points to another object.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports = {
  hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}
qinmu2127
  • 475
  • 5
  • 5
4

I found this link useful to answer the above question.

http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/

To add to the other posts The module system in node does

var exports = module.exports 

before executing your code. So when you want to exports = foo , you probably want to do module.exports = exports = foo but using exports.foo = foo should be fine

Paweł Gościcki
  • 7,644
  • 5
  • 57
  • 75
4

This shows how require() works in its simplest form, excerpted from Eloquent JavaScript

Problem It is not possible for a module to directly export a value other than the exports object, such as a function. For example, a module might want to export only the constructor of the object type it defines. Right now, it cannot do that because require always uses the exports object it creates as the exported value.

Solution Provide modules with another variable, module, which is an object that has a property exports. This property initially points at the empty object created by require but can be overwritten with another value in order to export something else.

function require(name) {
  if (name in require.cache)
    return require.cache[name];
  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);
  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);
onmyway133
  • 38,911
  • 23
  • 231
  • 237
  • I had to recreate this in Node and test a few things until I got, I suck. Basically, the inner function created for the module never even returns the exports object. So the "exports" object isn't actually reassigned in the module e.g. if you try to write exports = "this is now a string" directly. The object only exists as a reference. This is behaviour I don't think I've really picked up on properly until now. – danielgormly Feb 26 '16 at 04:07
4

Here is the result of

console.log("module:");
console.log(module);

console.log("exports:");
console.log(exports);

console.log("module.exports:");
console.log(module.exports);

enter image description here

Also:

if(module.exports === exports){
    console.log("YES");
}else{
    console.log("NO");
}

//YES

Note: The CommonJS specification only allows the use of the exports variable to expose public members. Therefore, the named exports pattern is the only one that is really compatible with the CommonJS specification. The use of module.exports is an extension provided by Node.js to support a broader range of module definition patterns.

serkan
  • 5,565
  • 2
  • 33
  • 43
4
var a = {},md={};

//Firstly,the exports and module.exports point the same empty Object

exp = a;//exports =a;
md.exp = a;//module.exports = a;

exp.attr = "change";

console.log(md.exp);//{attr:"change"}

//If you point exp to other object instead of point it's property to other object. The md.exp will be empty Object {}

var a ={},md={};
exp =a;
md.exp =a;

exp = function(){ console.log('Do nothing...'); };

console.log(md.exp); //{}
4

From the docs

The exports variable is available within a module's file-level scope, and is assigned the value of module.exports before the module is evaluated.

It allows a shortcut, so that module.exports.f = ... can be written more succinctly as exports.f = .... However, be aware that like any variable, if a new value is assigned to exports, it is no longer bound to module.exports:

It is just a variable pointing to module.exports.

Community
  • 1
  • 1
ANewGuyInTown
  • 4,341
  • 3
  • 29
  • 40
3

"If you want the root of your module's export to be a function (such as a constructor) or if you want to export a complete object in one assignment instead of building it one property at a time, assign it to module.exports instead of exports." - http://nodejs.org/api/modules.html

madKakoo
  • 109
  • 1
  • 4
3

Let's create one module with 2 ways:

One way

var aa = {
    a: () => {return 'a'},
    b: () => {return 'b'}
}

module.exports = aa;

Second way

exports.a = () => {return 'a';}
exports.b = () => {return 'b';}

And this is how require() will integrate module.

First way:

function require(){
    module.exports = {};
    var exports = module.exports;

    var aa = {
        a: () => {return 'a'},
        b: () => {return 'b'}
    }
    module.exports = aa;

    return module.exports;
}

Second way

function require(){
    module.exports = {};
    var exports = module.exports;

    exports.a = () => {return 'a';}
    exports.b = () => {return 'b';}

    return module.exports;
}
Dmitry Sergeev
  • 311
  • 5
  • 5
3

module.exports and exports both point to the same object before the module is evaluated.

Any property you add to the module.exports object will be available when your module is used in another module using require statement. exports is a shortcut made available for the same thing. For instance:

module.exports.add = (a, b) => a+b

is equivalent to writing:

exports.add = (a, b) => a+b

So it is okay as long as you do not assign a new value to exports variable. When you do something like this:

exports = (a, b) => a+b 

as you are assigning a new value to exports it no longer has reference to the exported object and thus will remain local to your module.

If you are planning to assign a new value to module.exports rather than adding new properties to the initial object made available, you should probably consider doing as given below:

module.exports = exports = (a, b) => a+b

Node.js website has a very good explanation of this.

2

1.exports -> use as singleton utility
2. module-exports -> use as logical objects such as service , model etc

Matt
  • 70,063
  • 26
  • 142
  • 172
riv
  • 21
  • 1
2

why both are used here

I believe they just want to be clear that module.exports, exports, and nano point to the same function - allowing you to use either variable to call the function within the file. nano provides some context to what the function does.

exports won't be exported (only module.exports will), so why bother overwriting that as well?

The verbosity trade-off limits the risk of future bugs, such as using exports instead of module.exports within the file. It also provides clarification that module.exports and exports are in fact pointing to the same value.


module.exports vs exports

As long as you don't reassign module.exports or exports (and instead add values to the object they both refer to), you won't have any issues and can safely use exports to be more concise.

When assigning either to a non-object, they are now pointing to different places which can be confusing unless you intentionally want module.exports to be something specific (such as a function).

Setting exports to a non-object doesn't make much sense as you'll have to set module.exports = exports at the end to be able to use it in other files.

let module = { exports: {} };
let exports = module.exports;

exports.msg = 'hi';
console.log(module.exports === exports); // true

exports = 'yo';
console.log(module.exports === exports); // false

exports = module.exports;
console.log(module.exports === exports); // true

module.exports = 'hello';
console.log(module.exports === exports); // false

module.exports = exports;
console.log(module.exports === exports); // true

Why assign module.exports to a function?

More concise! Compare how much shorter the 2nd example is:

helloWorld1.js: module.exports.hello = () => console.log('hello world');

app1.js: let sayHello = require('./helloWorld1'); sayHello.hello; // hello world

helloWorld2.js: module.exports = () => console.log('hello world');

app2.js: let sayHello = require('./helloWorld2'); sayHello; // hello world

Community
  • 1
  • 1
JBallin
  • 4,767
  • 33
  • 38
2

enter image description here

Each file you create is a module. module is an object. It has property called exports : {} which is empty object by default.

you can create functions/middlewares and add to this empty exports object such as exports.findById() => { ... } then require anywhere in your app and use...

controllers/user.js

exports.findById = () => {
    //  do something
}

require in routes.js to use:

const {findyId} = './controllers/user'
Ryan Dhungel
  • 1,824
  • 1
  • 14
  • 22
0

in node js module.js file is use to run the module.load system.every time when node execute a file it wrap your js file content as follow

'(function (exports, require, module, __filename, __dirname) {',+
     //your js file content
 '\n});'

because of this wrapping inside ur js source code you can access exports,require,module,etc.. this approach is used because there is no other way to get functionalities wrote in on js file to another.

then node execute this wrapped function using c++. at that moment exports object that passed into this function will be filled.

you can see inside this function parameters exports and module. actually exports is a public member of module constructor function.

look at following code

copy this code into b.js

console.log("module is "+Object.prototype.toString.call(module));
console.log("object.keys "+Object.keys(module));
console.log(module.exports);
console.log(exports === module.exports);
console.log("exports is "+Object.prototype.toString.call(exports));
console.log('----------------------------------------------');
var foo = require('a.js');
console.log("object.keys of foo: "+Object.keys(foo));
console.log('name is '+ foo);
foo();

copy this code to a.js

exports.name = 'hello';
module.exports.name = 'hi';
module.exports.age = 23;
module.exports = function(){console.log('function to module exports')};
//exports = function(){console.log('function to export');}

now run using node

this is the output

module is [object Object]
object.keys id,exports,parent,filename,loaded,children,paths
{}
true

exports is [object Object]

object.keys of foo: name is function (){console.log('function to module exports')} function to module exports

now remove the commented line in a.js and comment the line above that line and remove the last line of b.js and run.

in javascript world you cannot reassign object that passed as parameter but you can change function's public member when object of that function set as a parameter to another function

do remember

use module.exports on and only if you wants to get a function when you use require keyword . in above example we var foo = require(a.js); you can see we can call foo as a function;

this is how node documentation explain it "The exports object is created by the Module system. Sometimes this is not acceptable, many want their module to be an instance of some class. To do this assign the desired export object to module.exports."

sidias
  • 11
0
  1. Both module.exports and exports point to the same function database_module(cfg) {...}.

    1| var a, b;
    2| a = b = function() { console.log("Old"); };
    3|     b = function() { console.log("New"); };
    4|
    5| a(); // "Old"
    6| b(); // "New"
    

    You can change b on line 3 to a, the output is reverse. The conclusion is:

    a and b are independent.

  2. So module.exports = exports = nano = function database_module(cfg) {...} is equivalent to:

    var f = function database_module(cfg) {...};
    module.exports = f;
    exports = f;
    

    Assumed the above is module.js, which is required by foo.js. The benefits of module.exports = exports = nano = function database_module(cfg) {...} is clear now:

    • In foo.js, since module.exports is require('./module.js'):

      var output = require('./modules.js')();
      
    • In moduls.js: You can use exports instead of module.exports.

So, you will be happy if both exports and module.exports pointing to the same thing.

Rainning
  • 766
  • 3
  • 16
  • 40
0
  • exports: it's a reference to module.exports object
  • both exports and module.exports point to the same object until we change the reference of exports object

Example:

  1. if exports.a = 10 then module.exports.a = 10

  2. if we reassign exports object explicitly inside the code like exports = {} now its lost the reference to module.exports

Thofiq
  • 1
  • 1