I've found the following contract in a Node.js module:
module.exports = exports = nano = function database_module(cfg) {...}
I wonder what's the difference between module.exports and exports and why both are used here.
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;
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?
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.
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.
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.
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() { ... }
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}
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)
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')}
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;
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
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);
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);
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.
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); //{}
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.
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
"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
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;
}
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.
1.exports -> use as singleton utility
2. module-exports -> use as logical objects such as service , model etc
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
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'
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."
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.
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.
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:
if exports.a = 10 then module.exports.a = 10
if we reassign exports object explicitly inside the code like
exports = {} now its lost the reference to module.exports
Related
I've been working with nodejs lately and still getting to grips with the module system, so apologies if this is an obvious question. I want code roughly like the below:
a.js (the main file run with node)
var ClassB = require("./b");
var ClassA = function() {
this.thing = new ClassB();
this.property = 5;
}
var a = new ClassA();
module.exports = a;
b.js
var a = require("./a");
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
util.log(a.property);
}
module.exports = ClassB;
My problem seems to be that I can't access the instance of ClassA from within an instance of ClassB.
Is there any correct / better way to structure modules to achieve what I want?
Is there a better way to share variables across modules?
Try to set properties on module.exports, instead of replacing it completely. E.g., module.exports.instance = new ClassA() in a.js, module.exports.ClassB = ClassB in b.js. When you make circular module dependencies, the requiring module will get a reference to an incomplete module.exports from the required module, which you can add other properties latter on, but when you set the entire module.exports, you actually create a new object which the requiring module has no way to access.
While node.js does allow circular require dependencies, as you've found it can be pretty messy and you're probably better off restructuring your code to not need it. Maybe create a third class that uses the other two to accomplish what you need.
[EDIT] it's not 2015 and most libraries (i.e. express) have made updates with better patterns so circular dependencies are no longer necessary. I recommend simply not using them.
I know I'm digging up an old answer here...
The issue here is that module.exports is defined after you require ClassB.
(which JohnnyHK's link shows)
Circular dependencies work great in Node, they're just defined synchronously.
When used properly, they actually solve a lot of common node issues (like accessing express.js app from other files)
Just make sure your necessary exports are defined before you require a file with a circular dependency.
This will break:
var ClassA = function(){};
var ClassB = require('classB'); //will require ClassA, which has no exports yet
module.exports = ClassA;
This will work:
var ClassA = module.exports = function(){};
var ClassB = require('classB');
I use this pattern all the time for accessing the express.js app in other files:
var express = require('express');
var app = module.exports = express();
// load in other dependencies, which can now require this file and use app
Sometimes it is really artificial to introduce a third class (as JohnnyHK advises), so in addition to Ianzz:
If you do want to replace the module.exports, for example if you're creating a class (like the b.js file in the above example), this is possible as well, just make sure that in the file that is starting the circular require, the 'module.exports = ...' statement happens before the require statement.
a.js (the main file run with node)
var ClassB = require("./b");
var ClassA = function() {
this.thing = new ClassB();
this.property = 5;
}
var a = new ClassA();
module.exports = a;
b.js
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
util.log(a.property);
}
module.exports = ClassB;
var a = require("./a"); // <------ this is the only necessary change
The solution is to 'forward declare' your exports object before requiring any other controller. So if you structure all your modules like this and you won't run into any issues like that:
// Module exports forward declaration:
module.exports = {
};
// Controllers:
var other_module = require('./other_module');
// Functions:
var foo = function () {
};
// Module exports injects:
module.exports.foo = foo;
What about lazy requiring only when you need to? So your b.js looks as follows
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
var a = require("./a"); //a.js has finished by now
util.log(a.property);
}
module.exports = ClassB;
Of course it is good practice to put all require statements on top of the file. But there are occasions, where I forgive myself for picking something out of an otherwise unrelated module. Call it a hack, but sometimes this is better than introducing a further dependency, or adding an extra module or adding new structures (EventEmitter, etc)
You can solve this easily: just export your data before you require anything else in modules where you use module.exports:
classA.js
class ClassA {
constructor(){
ClassB.someMethod();
ClassB.anotherMethod();
};
static someMethod () {
console.log( 'Class A Doing someMethod' );
};
static anotherMethod () {
console.log( 'Class A Doing anotherMethod' );
};
};
module.exports = ClassA;
var ClassB = require( "./classB.js" );
let classX = new ClassA();
classB.js
class ClassB {
constructor(){
ClassA.someMethod();
ClassA.anotherMethod();
};
static someMethod () {
console.log( 'Class B Doing someMethod' );
};
static anotherMethod () {
console.log( 'Class A Doing anotherMethod' );
};
};
module.exports = ClassB;
var ClassA = require( "./classA.js" );
let classX = new ClassB();
A solution which require minimal change is extending module.exports instead of overriding it.
a.js - app entry point and module which use method do from b.js*
_ = require('underscore'); //underscore provides extend() for shallow extend
b = require('./b'); //module `a` uses module `b`
_.extend(module.exports, {
do: function () {
console.log('doing a');
}
});
b.do();//call `b.do()` which in turn will circularly call `a.do()`
b.js - module which use method do from a.js
_ = require('underscore');
a = require('./a');
_.extend(module.exports, {
do: function(){
console.log('doing b');
a.do();//Call `b.do()` from `a.do()` when `a` just initalized
}
})
It will work and produce:
doing b
doing a
While this code will not work:
a.js
b = require('./b');
module.exports = {
do: function () {
console.log('doing a');
}
};
b.do();
b.js
a = require('./a');
module.exports = {
do: function () {
console.log('doing b');
}
};
a.do();
Output:
node a.js
b.js:7
a.do();
^
TypeError: a.do is not a function
The important thing is not to re-assign the module.exports object that you have been given, because that object may have already been given to other modules in the cycle! Just assign properties inside module.exports and other modules will see them appear.
So a simple solution is:
module.exports.firstMember = ___;
module.exports.secondMember = ___;
The only real downside is the need to repeat module.exports. many times.
Similar to lanzz and setec's answers, I have been using the following pattern, which feels more declarative:
module.exports = Object.assign(module.exports, {
firstMember: ___,
secondMember: ___,
});
The Object.assign() copies the members into the exports object that has already been given to other modules.
The = assignment is logically redundant, since it is just setting module.exports to itself, but I am using it because it helps my IDE (WebStorm) to recognise that firstMember is a property of this module, so "Go To -> Declaration" (Cmd-B) and other tooling will work from other files.
This pattern is not very pretty, so I only use it when a cyclic dependency issue needs to be resolved.
It is fairly well suited to the reveal pattern, because you can easily add and remove exports from the object, especially when using ES6's property shorthand.
Object.assign(module.exports, {
firstMember,
//secondMember,
});
the extremely simple solution is often:
usually you'd have the require at the top of the file ...
var script = require('./script')
function stuff() {
script.farfunction()
}
instead, just require it "in the function"
function stuff() {
var _script = require('./script')
_script.farfunction()
}
An other method I've seen people do is exporting at the first line and saving it as a local variable like this:
let self = module.exports = {};
const a = require('./a');
// Exporting the necessary functions
self.func = function() { ... }
I tend to use this method, do you know about any downsides of it?
TL;DR
Just use exports.someMember = someMember instead of module.exports = { // new object }.
Extended Answer
After reading lanzz's response I could finally figure it out what is happening here, so I'll give my two cents on the subject, extending his answer.
Let's see this example:
a.js
console.log("a starting");
console.log("a requires b");
const b = require("./b");
console.log("a gets b =", b);
function functionA() {
console.log("function a");
}
console.log("a done");
exports.functionA = functionA;
b.js
console.log("b starting");
console.log("b requires a");
const a = require("./a");
console.log("b gets a =", a);
function functionB() {
console.log("On b, a =", a)
}
console.log("b done");
exports.functionB = functionB;
main.js
const a = require("./a");
const b = require("./b");
b.functionB()
Output
a starting
a requires b
b starting
b requires a
b gets a = {}
b done
a gets b = { functionB: [Function: functionB] }
a done
On b, a = { functionA: [Function: functionA] }
Here we can see that at first b receives an empty object as a, and then once a is fully loaded, that reference is updated through exports.functionA = functionA. If you instead replace the entire module with another object, through module.exports, then b will lose the reference from a, since it will point out to the same empty object from the beginning, instead of pointing to the new one.
So if you export a like this: module.exports = { functionA: functionA }, then the output will be:
a starting
a requires b
b starting
b requires a
b gets a = {}
b done
a gets b = { functionB: [Function: functionB] }
a done
On b, a = {} // same empty object
Actually I ended up requiring my dependency with
var a = null;
process.nextTick(()=>a=require("./a")); //Circular reference!
not pretty, but it works. It is more understandable and honest than changing b.js (for example only augmenting modules.export), which otherwise is perfect as is.
Here is a quick workaround that I've found use full.
On file 'a.js'
let B;
class A{
constructor(){
process.nextTick(()=>{
B = require('./b')
})
}
}
module.exports = new A();
On the file 'b.js' write the following
let A;
class B{
constructor(){
process.nextTick(()=>{
A = require('./a')
})
}
}
module.exports = new B();
This way on the next iteration of the event loop classes will be defined correctly and those require statements will work as expected.
One way to avoid it is to don't require one file in other just pass it as an argument to a function what ever you need in an another file.
By this way circular dependency will never arise.
If you just can't eliminate circular dependencies (e.g useraccount <---> userlogin), there's one more option...
Its as simple as using setTimeout()
//useraccount.js
let UserLogin = {};
setTimeout(()=>UserLogin=require('./userlogin.js'), 10);
class UserAccount{
getLogin(){
return new UserLogin(this.email);
}
}
//userlogin.js
let UserAccount ={};
setTimeout(()=>UserAccount=require('./useraccount.js'), 15);
class UserLogin{
getUser(){
return new User(this.token);
}
}
I'm having trouble understanding the difference between exporting modules like:
module.exports.getUserIP = function getUserIP(req) {
var ip = req.headers['x-forwarded-for'];
return ip;
}
Or just declaring it:
function getUserIP(req) {
// retrieve user IP from req object
// Build this function to be more accurate/use more sources.
var ip = req.headers['x-forwarded-for'];
return ip;
}
and exporting at the bottom:
module.exports = { getUserIP }
or even:
module.exports = {getUserIP:getUserIP}
or
module.exports = {'getUserIP':getUserIP}
My problem is: when i call the function getUserIP from another file:
var mainbody = require('./app.js');//getUserIP is in here.
const gl = require('geoip-lite');
var ax = require('axios');
module.exports.getloc = function getloc(req, ip, property) {
//return location from IP.
if (req) {
var ipGuest = mainbody.getUserIP(req); //HERE
} else {
var ipGuest = ip;
}....
I get an error message:
Error Message
However, when I use the FIRST method to export the function:
module.exports.getUserIP = function getUserIP(req) {
var ip = req.headers['x-forwarded-for'];
return ip;
}
Then it works perfectly.
What's the difference?
Better way is to use
module.exports = { getUserIP: getUserIP }
This way you can just look at the export statement at the end of your file and know which functions are being exported from a particular file
The module.exports = {getUserIP}; is nothing but a shorthand of the above syntax(ES6 Magic). What it typically does is allows you to write this way { getUserIP } if the key name to be same as function/variable name like { getUserIP: getUserIP } where getUserIP can be a variable or a function or a ES6 class.
All the examples you show will work properly, but they do have some different affects.
By default module.exports is already initialized to an empty object. So, when you do something like this:
module.exports.getUserIP = function() {...}
You are assigning a new property to the existing object that module.exports already pointed to. One advantage of this scheme is that you can easily add more properties the same way.
module.exports.getUserRegion = function() {}
This will add one more property to that same object without disturbing the first one you already added.
On the other hand, all of these are identical:
module.exports = {getUserIP: getUserIP}
module.exports = {'getUserIP':getUserIP}
module.exports = { getUserIP } // ES6 shorthand for the previous syntax
and, they all end up with the same result as each other, but they all replace module.exports with a new object that has your one new property in it.
If you then tried to add another property:
module.exports = {getUserRegion};
That would again assign a whole new object to module.exports and you would have just wiped out the object that previously had getUserIP on it. When assigning a new object, you would typically assign an object that had all your properties on it:
module.exports = {getUserIP: function() {...}, getUserRegion: function() {...}};
Thus, not wiping out something you had already put there.
All of your schemes should work fine as long as you aren't overwriting module.exports with a new object and thus overwriting the object that already had some of your methods on it.
To understand this exporting modules concept, just think module.export is a simple object. you can bind anything to that object as do with normal javascript objects.
Finally when you require that module by require('path to js') you will get that exported object. If you export number of items in your module you can return them back by giving the names of the tag.
I was trying to follow basic guide on modules. I've created test_module.js
var textFunction = function() {
console.log("text");
};
exports = textFunction;
And then I tried to use it in my app.js:
var textFunction = ('./test_module');
textFunction();
But I get an error:
TypeError: textFunction is not a function
Am I doing something wrong? Or it was a very old guide?
PS: exports works only if I declare it like this:
exports.text = function() {
console.log("text");
}
exports is a local variable. Assigning to it won't change the exported value. You want to assign to module.exports directly:
module.exports = textFunction;
module.exports and exports initially refer to the same value (an object), but assigning to exports won't change module.exports, which is what counts. exports exists for convenience.
The other issue is that you are not properly requiring the module, but that may just be a typo. You should be doing
var textFunction = require('./test_module');
var textFunction = ('./test_module'); just assigns the string './test_module' to textFunction and we all know that strings are not functions.
My module.exports = foo is returning a blank object {}. Can anyone explain this?
Only if i use exports = module.exports = foo that my object isn't blank.
module.exports is the variable that matters when defining exports. It's the actual object that will be returned from the require('moduleName') statement.
For convenience, node predefines exports as an alias essentiallly via:
var exports = module.exports;
That way you can then assign to either module.exports or just to exports. So, you can do either of these and they create the same result because module.exports === exports:
module.exports.myFunc1 = function() {};
module.exports.myFunc2 = function() {};
or this:
exports.myFunc1 = function() {};
exports.myFunc2 = function() {};
But, when you redefine module.exports by assigning a new object to it, then exports is no longer the same object as module.exports.
module.exports = {
myFunc1: function() {},
myFunc2: function() {}
};
Now, exports !== module.exports because you assigned a new object to module.exports and exports still points to the original module.exports.
So, to preserve the way it was originally (in case any other code in your module refers to exports, it is common to make sure that exports is again the same as module.exports with code like this:
module.exports = exports = {
myFunc1: function() {},
myFunc2: function() {}
};
If the code in your module never refers to exports itself, then you do not need to use it in any way because only module.exports actually matters to the outside world.
There is two ways to fullfill exports for your module. Choose whatever you like.
1) You can use add multiple properties to your module like that:
exports.foo = function () {};
exports.bar = function () {};
2) You can define single object like class, for example.
module.exports = Module;
function Module () {}
exports is just an alias for module.exports.
Use it when you want to return a object from your module, fullfilled with multiple properties.
Use module.exports when you want to return just a single value from your module.
If you define your module with module.exports, export itself becomes just a predefined variable, and you don't need to rewrite it.
All this you can find in docs
http://nodejs.org/api/modules.html#modules_the_module_object
I've been working with nodejs lately and still getting to grips with the module system, so apologies if this is an obvious question. I want code roughly like the below:
a.js (the main file run with node)
var ClassB = require("./b");
var ClassA = function() {
this.thing = new ClassB();
this.property = 5;
}
var a = new ClassA();
module.exports = a;
b.js
var a = require("./a");
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
util.log(a.property);
}
module.exports = ClassB;
My problem seems to be that I can't access the instance of ClassA from within an instance of ClassB.
Is there any correct / better way to structure modules to achieve what I want?
Is there a better way to share variables across modules?
Try to set properties on module.exports, instead of replacing it completely. E.g., module.exports.instance = new ClassA() in a.js, module.exports.ClassB = ClassB in b.js. When you make circular module dependencies, the requiring module will get a reference to an incomplete module.exports from the required module, which you can add other properties latter on, but when you set the entire module.exports, you actually create a new object which the requiring module has no way to access.
While node.js does allow circular require dependencies, as you've found it can be pretty messy and you're probably better off restructuring your code to not need it. Maybe create a third class that uses the other two to accomplish what you need.
[EDIT] it's not 2015 and most libraries (i.e. express) have made updates with better patterns so circular dependencies are no longer necessary. I recommend simply not using them.
I know I'm digging up an old answer here...
The issue here is that module.exports is defined after you require ClassB.
(which JohnnyHK's link shows)
Circular dependencies work great in Node, they're just defined synchronously.
When used properly, they actually solve a lot of common node issues (like accessing express.js app from other files)
Just make sure your necessary exports are defined before you require a file with a circular dependency.
This will break:
var ClassA = function(){};
var ClassB = require('classB'); //will require ClassA, which has no exports yet
module.exports = ClassA;
This will work:
var ClassA = module.exports = function(){};
var ClassB = require('classB');
I use this pattern all the time for accessing the express.js app in other files:
var express = require('express');
var app = module.exports = express();
// load in other dependencies, which can now require this file and use app
Sometimes it is really artificial to introduce a third class (as JohnnyHK advises), so in addition to Ianzz:
If you do want to replace the module.exports, for example if you're creating a class (like the b.js file in the above example), this is possible as well, just make sure that in the file that is starting the circular require, the 'module.exports = ...' statement happens before the require statement.
a.js (the main file run with node)
var ClassB = require("./b");
var ClassA = function() {
this.thing = new ClassB();
this.property = 5;
}
var a = new ClassA();
module.exports = a;
b.js
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
util.log(a.property);
}
module.exports = ClassB;
var a = require("./a"); // <------ this is the only necessary change
The solution is to 'forward declare' your exports object before requiring any other controller. So if you structure all your modules like this and you won't run into any issues like that:
// Module exports forward declaration:
module.exports = {
};
// Controllers:
var other_module = require('./other_module');
// Functions:
var foo = function () {
};
// Module exports injects:
module.exports.foo = foo;
What about lazy requiring only when you need to? So your b.js looks as follows
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
var a = require("./a"); //a.js has finished by now
util.log(a.property);
}
module.exports = ClassB;
Of course it is good practice to put all require statements on top of the file. But there are occasions, where I forgive myself for picking something out of an otherwise unrelated module. Call it a hack, but sometimes this is better than introducing a further dependency, or adding an extra module or adding new structures (EventEmitter, etc)
You can solve this easily: just export your data before you require anything else in modules where you use module.exports:
classA.js
class ClassA {
constructor(){
ClassB.someMethod();
ClassB.anotherMethod();
};
static someMethod () {
console.log( 'Class A Doing someMethod' );
};
static anotherMethod () {
console.log( 'Class A Doing anotherMethod' );
};
};
module.exports = ClassA;
var ClassB = require( "./classB.js" );
let classX = new ClassA();
classB.js
class ClassB {
constructor(){
ClassA.someMethod();
ClassA.anotherMethod();
};
static someMethod () {
console.log( 'Class B Doing someMethod' );
};
static anotherMethod () {
console.log( 'Class A Doing anotherMethod' );
};
};
module.exports = ClassB;
var ClassA = require( "./classA.js" );
let classX = new ClassB();
A solution which require minimal change is extending module.exports instead of overriding it.
a.js - app entry point and module which use method do from b.js*
_ = require('underscore'); //underscore provides extend() for shallow extend
b = require('./b'); //module `a` uses module `b`
_.extend(module.exports, {
do: function () {
console.log('doing a');
}
});
b.do();//call `b.do()` which in turn will circularly call `a.do()`
b.js - module which use method do from a.js
_ = require('underscore');
a = require('./a');
_.extend(module.exports, {
do: function(){
console.log('doing b');
a.do();//Call `b.do()` from `a.do()` when `a` just initalized
}
})
It will work and produce:
doing b
doing a
While this code will not work:
a.js
b = require('./b');
module.exports = {
do: function () {
console.log('doing a');
}
};
b.do();
b.js
a = require('./a');
module.exports = {
do: function () {
console.log('doing b');
}
};
a.do();
Output:
node a.js
b.js:7
a.do();
^
TypeError: a.do is not a function
The important thing is not to re-assign the module.exports object that you have been given, because that object may have already been given to other modules in the cycle! Just assign properties inside module.exports and other modules will see them appear.
So a simple solution is:
module.exports.firstMember = ___;
module.exports.secondMember = ___;
The only real downside is the need to repeat module.exports. many times.
Similar to lanzz and setec's answers, I have been using the following pattern, which feels more declarative:
module.exports = Object.assign(module.exports, {
firstMember: ___,
secondMember: ___,
});
The Object.assign() copies the members into the exports object that has already been given to other modules.
The = assignment is logically redundant, since it is just setting module.exports to itself, but I am using it because it helps my IDE (WebStorm) to recognise that firstMember is a property of this module, so "Go To -> Declaration" (Cmd-B) and other tooling will work from other files.
This pattern is not very pretty, so I only use it when a cyclic dependency issue needs to be resolved.
It is fairly well suited to the reveal pattern, because you can easily add and remove exports from the object, especially when using ES6's property shorthand.
Object.assign(module.exports, {
firstMember,
//secondMember,
});
the extremely simple solution is often:
usually you'd have the require at the top of the file ...
var script = require('./script')
function stuff() {
script.farfunction()
}
instead, just require it "in the function"
function stuff() {
var _script = require('./script')
_script.farfunction()
}
An other method I've seen people do is exporting at the first line and saving it as a local variable like this:
let self = module.exports = {};
const a = require('./a');
// Exporting the necessary functions
self.func = function() { ... }
I tend to use this method, do you know about any downsides of it?
TL;DR
Just use exports.someMember = someMember instead of module.exports = { // new object }.
Extended Answer
After reading lanzz's response I could finally figure it out what is happening here, so I'll give my two cents on the subject, extending his answer.
Let's see this example:
a.js
console.log("a starting");
console.log("a requires b");
const b = require("./b");
console.log("a gets b =", b);
function functionA() {
console.log("function a");
}
console.log("a done");
exports.functionA = functionA;
b.js
console.log("b starting");
console.log("b requires a");
const a = require("./a");
console.log("b gets a =", a);
function functionB() {
console.log("On b, a =", a)
}
console.log("b done");
exports.functionB = functionB;
main.js
const a = require("./a");
const b = require("./b");
b.functionB()
Output
a starting
a requires b
b starting
b requires a
b gets a = {}
b done
a gets b = { functionB: [Function: functionB] }
a done
On b, a = { functionA: [Function: functionA] }
Here we can see that at first b receives an empty object as a, and then once a is fully loaded, that reference is updated through exports.functionA = functionA. If you instead replace the entire module with another object, through module.exports, then b will lose the reference from a, since it will point out to the same empty object from the beginning, instead of pointing to the new one.
So if you export a like this: module.exports = { functionA: functionA }, then the output will be:
a starting
a requires b
b starting
b requires a
b gets a = {}
b done
a gets b = { functionB: [Function: functionB] }
a done
On b, a = {} // same empty object
Actually I ended up requiring my dependency with
var a = null;
process.nextTick(()=>a=require("./a")); //Circular reference!
not pretty, but it works. It is more understandable and honest than changing b.js (for example only augmenting modules.export), which otherwise is perfect as is.
Here is a quick workaround that I've found use full.
On file 'a.js'
let B;
class A{
constructor(){
process.nextTick(()=>{
B = require('./b')
})
}
}
module.exports = new A();
On the file 'b.js' write the following
let A;
class B{
constructor(){
process.nextTick(()=>{
A = require('./a')
})
}
}
module.exports = new B();
This way on the next iteration of the event loop classes will be defined correctly and those require statements will work as expected.
One way to avoid it is to don't require one file in other just pass it as an argument to a function what ever you need in an another file.
By this way circular dependency will never arise.
If you just can't eliminate circular dependencies (e.g useraccount <---> userlogin), there's one more option...
Its as simple as using setTimeout()
//useraccount.js
let UserLogin = {};
setTimeout(()=>UserLogin=require('./userlogin.js'), 10);
class UserAccount{
getLogin(){
return new UserLogin(this.email);
}
}
//userlogin.js
let UserAccount ={};
setTimeout(()=>UserAccount=require('./useraccount.js'), 15);
class UserLogin{
getUser(){
return new User(this.token);
}
}