On this page (http://docs.nodejitsu.com/articles/getting-started/what-is-require), it states that "If you want to set the exports object to a function or a new object, you have to use the module.exports object."
My question is why.
// right
module.exports = function () {
console.log("hello world")
}
// wrong
exports = function () {
console.log("hello world")
}
I console.logged the result (result=require(example.js)
) and the first one is [Function]
the second one is {}
.
Could you please explain the reason behind it? I read the post here: module.exports vs exports in Node.js . It is helpful, but does not explain the reason why it is designed in that way. Will there be a problem if the reference of exports be returned directly?
Rene's answer about the relationship between
exports
andmodule.exports
is quite clear, it's all about javascript references. Just want to add that:We see this in many node modules:
var app = exports = module.exports = {};
This will make sure that even if we changed module.exports, we can still use exports by making those two variables point to the same object.
module
is a plain JavaScript object with anexports
property.exports
is a plain JavaScript variable that happens to be set tomodule.exports
. At the end of your file, node.js will basically 'return'module.exports
to therequire
function. A simplified way to view a JS file in Node could be this:If you set a property on
exports
, likeexports.a = 9;
, that will setmodule.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 thenexports
andmodule.exports
are the same object.But if you set
exports
to something new, it will no longer be set tomodule.exports
, soexports
andmodule.exports
are no longer the same object.Also, one things that may help to understand:
math.js
client.js
Great, in this case:
Thus, by default, "this" is actually equals to module.exports.
However, if you change your implementation to:
math.js
In this case, it will work fine, however, "this" is not equal to module.exports anymore, because a new object was created.
And now, what will be returned by the require is what was defined inside the module.exports, not this or exports, anymore.
Another way to do it would be:
math.js
Or:
math.js
Renee's answer is well explained. Addition to the answer with an example:
Node does a lot of things to your file and one of the important is WRAPPING your file. Inside nodejs source code "module.exports" is returned. Lets take a step back and understand the wrapper. Suppose you have
greet.js
the above code is wrapped as IIFE(Immediately Invoked Function Expression) inside nodejs source code as follows:
and the above function is invoked (.apply()) and returned module.exports. At this time module.exports and exports pointing to the same reference.
Now, imagine you re-write greet.js as
the output will be
the reason is : module.exports is an empty object. We did not set anything to module.exports rather we set exports = function()..... in new greet.js. So, module.exports is empty.
Technically exports and module.exports should point to same reference(thats correct!!). But we use "=" when assigning function().... to exports, which creates another object in the memory. So, module.exports and exports produce different results. When it comes to exports we can't override it.
Now, imagine you re-write (this is called Mutation) greet.js (referring to Renee answer) as
the output will be
As you can see module.exports and exports are pointing to same reference which is a function. If you set a property on exports then it will be set on module.exports because in JS, objects are pass by reference.
Conclusion is always use module.exports to avoid confusion. Hope this helps. Happy coding :)