meaning of module.exports= function in node.js - javascript

I am taking first steps with node.js and obviously one of the first things i tried to do was exporting some data from a module, so i tried this simple case:
dummy.js:
var user = "rally";
module.exports = {
user:user
};
and than required it from a different file like this:
var dummy = require('./dummy.js');
console.log(dummy.user); // rally
So far so good, every thing works, but now i dived into code where there is this definition in the beginning of the module:
module.exports = function(passport,config, mongoose) {}
and i don't understand whats the meaning of it and how can i work with it.
just for trying to understand i defined some variables inside this abstract function but couldn't get their value from any other file.
any idea how can i export variables from module defined like this..? so for example i could require this module and get the "Dummy" variable and use it in a different file
module.exports = function(passport,config, mongoose) {
var dummy = "Dummy";
}

It works exactly the same as the first one does, only that it exports a function instead of an object.
The module that imports the module can then call that function:
var dummy = require('./dummy.js');
dummy();
any idea how can i export variables from module defined like this..?
Since functions are just objects, you can also assign properties to it:
module.exports = function(passport,config, mongoose) {}
module.exports.user = 'rally';
However I'd argue that this is less expected if a module directly exports a function. You are probably better off exporting the function as its own export:
exports.login = function(passport,config, mongoose) {}
exports.user = 'rally';

WHAT IS A MODULE?
A module encapsulates related code into a single unit of code. When creating a module, this can be interpreted as moving all related functions into a file.
// dummy.js
var exports = module.exports = {};
The utility of dummy.js increases when its encapsulated code can be utilized in other files. This is achieved by using exports.
HOW ARE THEY INVOKED?
You could declare your functions outside of the module.exports block. Functions inside exports can be invoked exactly the same way as variables or any other object.
EXAMPLE
//dummy.js
var myVariable = "foo";
var myFunction = function(){
//some logic
};
module.exports{
myVariable : myVariable,
myFunction : myFunction,
myVariableTypeTwo : "bar",
myFunctionTypeTwo : function () {
//some logic
}
}
We can now access the publicly available methods of dummy.js as a property from any js file.
var dummy = require('./dummy.js');
dummy.myVariable; //foo
dummy.myFunction();
dummy.myVariableTypeTwo; //bar
dummy.myFunctionTypeTwo();
NOTE
In the code above, we could have replaced module.exports with exports and achieved the same result. If this seems confusing, remember that exports and module.exports reference the same object.

Related

export.something Javascript

Here is a code snippet
body.user_id = userObj._id;
exports.inFCID(conn, obj.fcid, body, fcid, 0).then(function (r) {
exports.getUserById(conn, body.user_id).then(function (u) {
console.log("after getuserbyid", u);
Here I am sort of didn't understand why user have done something like
exports.inFCID(conn, obj.fcid, body, fcid, 0).then(function (r
of to be precise what does it do? I have previously encounter things like module.exports and export default statement ( export something statements) but this seems to be new.. Can someone explain me what this snippets would normally do? Ignoring what is inside those functions (inFCID) or what does export.something do in middle of the code..
It's expected that inFCID export is defined in this module as well:
exports.inFCID = function inFCID (...) {...};
When an export is defined as function expression, inFCID function is not available as inFCID but as exports.inFCID.
Referring exported functions as exports.inFCID inside module is a common recipe to improve testability in CommonJS modules; the same recipe won't work with ESM; a module needs to be separated when used with ES modules, as explained in this answer. Module exports can be spied or mocked outside the module:
const foo = require('foo');
...
spyOn(foo, 'inFCID');
foo.bar();
expect(foo.inFCID).toHaveBeenCalled();
This would be impossible if inFCID(...) was referred directly.
exports is a regular object.
If you have a code like this:
function test() {}
module.exports.test = test
Then nodejs will convert it into something like this:
function moduleInvocation(module, exports) {
function test() {}
module.exports.test = test
}
// a rough dummy code, to illustrat what node does on require
function require(moduleName) {
var module = { exports : {} };
//
// some code that loades `moduleName` and wraps it into `moduleInvocation`
//
moduleInvocation(module, module.exports)
return module;
}
So if someone writes exports.inFCID() then it is not different to:
var obj = {};
obj.inFCID = function() {}
obj.inFCID();
But it does not make any sense to write it that way except if you compose the exports of the module out of the content of some sub files.

Nodejs module exports confusion

I have a confusion with module.exports. As far as I understood module.exports is an object that is exposed to other modules,
exports=module.exports={}
But in the index.js of morgan package in node.js I found this.
module.exports = morgan
module.exports.compile = compile
module.exports.format = format
module.exports.token = token
morgan, compile, format and token are all functions.
Can you explain whats happening here? How is a function(morgan) assigned to module.exports ? After the first line is executed, is module.exports a function instead of an JSON object?
A Node module basically works like this:
var module = {
exports: {}
};
(function (exports, require, module, __filename, __dirname) {
// your module code here
})(module.exports, require, module, __filename, __dirname);
var exported = module.exports;
By default, exports, and module.exports both point to the same object. You can add properties to the object as normal. However, what if you want to return a function or some other object instead of just the default standard object?
In that case, you can set module.exports to something else, and that will be the new exported object.
module.exports = function() {};
And of course, that function can have properties too, so your code is kind-of like this:
module.exports = function(){};
module.exports.compile = function() {};
module.exports.format = function() {};
module.exports.token = function() {};
Which would be equivalent to:
var morgan = function() {};
var compile = function() {};
var format = function() {};
var token = function() {};
morgan.compile = compile;
morgan.format = format;
morgan.token = token;
module.exports = morgan;
How is a function(morgan) assigned to module.exports ? After the first line is executed, is module.exports a function instead of an JSON object?
Yes, module.exports will be a function, in place of the default object (however there is no JSON here, JSON is not a JavaScript object, but an encoding format).
You might want to read this answer for a more in-depth explanation:
What is the purpose of node js module exports and how do you use it?
Morgan is simply adding parameters to the module being exported (in this case compile, format, and token. When you require the module in your application using something like morgan = require('morgan'), you can then call morgan.format to return the format that was appended to the object.
Hope that clears things up a bit!
module.exports is an object that is exposed to other modules and files. This allows a convenient way to export variables, functions and more javascript features.
As you can see here , when you initialize any variable to {} you are initializing an object.
An object can contain variables and functions, this is one of the things that makes Javascript really cool. You can easily pass complex objects with functions as parameters and do real nice clean code.
So, short story, think about module.exports as an object that is exposed to other modules and files with variables and functions. Just like passing an Object Oriented object as a parameter in Java or Ruby.
Here is easily explained: Read More
Can you explain whats happening here?
An assignment statement is happening.
// path-to-my-module.js
module.exports = morgan
module.exports.compile = compile
module.exports.format = format
module.exports.token = token
For each of these 4 statements, there is an assignment statement. Looking at the first line, module.exports = morgan, that would mean the module.exports object is going to have a property called morgan with its value being the value of the identifier morgan
So when you use it like this:
var m = require('./path-to-my-module.js');
console.log(m.morgan);
console.log(m);

Creating Node.JS Module

I have been creating software in NodeJS for years, but I have rarely ever looked into the module side of it, since I've never needed to do that stuff myself.
I have created a test.js file, which is my module, all it contains is this (i've tried this.host, self.host, var host ... nothing is working)
var tests = function () {
this.host = "http://127.0.0.1/";
};
exports = tests;
In my server.js I try and use it and I can never get host to actually output
var tests = require('./test.js');
console.log(tests);
console.log(tests.host);
I always get this output, saying that tests variable has no properties ... which I set in the module.
sudo node server.js
{}
undefined
The host variable as you defined it in the tests function is not accessible through tests's prototype.
This means that in order to access it, you should be creating a new instance of tests, using the new operator :
var Tests = require('./tests');
var instance = new Tests();
// Now you can access `instance.host`
Also, as David said, use module.exports to export your function.
Don't do exports = tests. Either do exports.tests = tests or module.exports = tests.
Basically, you have to first decide if you want your module to just have properties that can be directly accessed or if you want it to have a constructor function that creates an object when it is called that then has properties or it could even just be a regular function that you call that returns a value. You have mixed and matched the first two schemes (pieces of each) and thus it does not work. I will show you both schemes:
Here's the scheme where your module exports a constructor function from which you can create an object (when you new it):
// test.js module
var tests = function () {
this.host = "http://127.0.0.1/";
};
module.exports = tests;
// main module server.js
var Tests = require('./test.js');
var t = new Tests();
console.log(t.host);
And, here's the scheme where you just directly export properties:
// test.js module
module.exports = {
host: "http://127.0.0.1/"
};
// main module server.js
var tests = require('./test.js');
console.log(tests);
console.log(tests.host);
Keep in mind that whatever you assign to module.exports is what require() will return after it loads your module. So, in your first case, you're assigning a function that is intended to be a constructor function so you have to use it as a constructor function in order for it to work properly.
In my second example, I assign an object to module.exports so you can then treat it just like an object after loading the module with require(). That means you can then just directly access its properties as you would for an object.
console.log(tests()); will work if the you add return statement inside the function.

How to pass variables into NodeJS modules?

In one of my JS files I include another one. How can I set variables in the included module?
I thought doing something like this would work
var mymodule = require('mymodule.js');
mymodule.myvariable = 'test';
And then in mymodule
this.myvariable === 'test';
But this doesn't work, it's undefined. What are the various options for passing a value into a module? I could just add the variable as a parameter to every function I call in mymodule, but that isn't ideal.
Is there a way to do it without globals, so that I can set the variables independently in various required modules, like this?
var mymodule1 = require('mymodule.js');
var mymodule2 = require('mymodule.js');
mymodule1.myvariable = 'test1';
mymodule2.myvariable = 'test2';
The problem with what you were doing is that you set the variable after importing, but this.myvariable === 'test'; was being called when the module was imported, before your variable was set.
You can have your module export a function and then call the function when you import, passing your variable as an argument.
module.exports = function(myVar) {
var myModule = {
// has access to myVar
...
};
return myModule;
};
When you import,
var myModule = require('myModule')(myVar);
If you use this method, keep in mind that you get a different instance of your module wherever you import, which may not be what you want.
If you want to set values of a module from outside the module, a good option is to have your module export an object with a setter method, and use that to set the value of the variable as a property of the object. This makes it more clear that you want this value to be settable, whereas just doing myModule.myVar = can set you up for confusion later.
module.exports = {
myVar: null,
setMyVar: function(myVar) {
this.myVar = myVar;
},
...
};
In this case you're accessing the same instance of the model wherever you import it.
Edit in response to comment
In the first option you show where you get a different instance each
time, how can I export multiple functions that each share the same
myVar? If that module exports 5 functions each that need myVar, can I
set it in one place like at import time rather than passing it into
each function?
Not entirely sure if I understand what you're describing, but you could do something like this:
module.exports = function(myVar) {
var modules = {};
modules.someModule = {...};
modules.anotherModule = {...};
...
return modules;
};
Each of these sub-modules would have access to the same myVar. So you would import as above and the result would be an object containing each of your five modules as properties. I can't say whether this is a good idea, it's getting pretty convoluted, but maybe it makes sense for your situation.
NodeJS require() will always load the module once so you will need to implement scoping into your module where different instances of the module can exist with their own internal state.
You can implement your module as a JS class like:
var MyModule = function(){};
MyModule.prototype.someFunction = function(params){
this.someVar = params;
}
MyModule.prototype.anotherFunction = function(key, value){
this[key] = value;
}
module.exports = MyModule;
Then in your code;
var MyModule = require('MyModule');
someModule = new MyModule();
// treat someModule like an object with its getters/setters/functions
Should work just fine. Here is a working example:
index.js
var module = require('./module.js');
module.myvar = 'Hello world';
module.test();
module.js
module.exports = {
test: function() {
console.log('var is', this.myvar);
}
};
Keep in mind if you use this in a closure that the scope isn't any longer the module itself. So that could be your problem.
Can you show me the part of the module code where you use this?
This is a module named StrUpperCase.js
exports.StrUpperCase = function(str) {
return str.toUpperCase();
}
In app.js:
var str = "Welcome World...";
const SUC = require('./modules/StrUpperCase');
console.log(SUC.StrUpperCase(str));

In Node.JS, how do I return an entire object from a separate .js file?

I am new to Node.js and trying to figure out how to request an object from a separate file (rather than just requesting a function) but everything I try--exports,module-exports,etc--is failing.
So, for example, if I have foo.js:
var methods = {
Foobar:{
getFoo: function(){return "foo!!";},
getBar: function(){return "bar!!";}
}
};
module.exports = methods;
And now I want to call a function within an object of foo.js from index.js:
var m = require('./foo');
function fooMain(){
return m.Foobar.getFoo();
};
How do I do this? I have tried all sorts of combinations of exports and module-exports but they seem to only work if I call a discrete function that is not part of an object.
You said that you tried exports, but your code doesn't show it. Anything that you want to be visible from outside your module must be assigned to (or otherwise be referable from) module.exports. In your case, where you have an object already, you can just assign it to module.exports:
var methods = {
...
};
// You must export the methods explicitly
module.exports = methods;
module.exports isn't magic, it's a normal object, and you can treat it as such. Meaning that you could have assigned your methods directly to it, as in:
module.exports.Foobar = {};
module.exports.Foobar.getFoo = function() { ... };
...
Or, as you probably know, you could event replace it with a function:
module.exports = function() { return "It's ALWAYS over 9000!!!!"; };
Only after exporting will you be able to use anything in another module.

Categories

Resources