Calling functions from a parameterized module.exports - javascript

Referencing this solution, I need to pass a parameter into module.exports of my utils.js file.
// utils.js
var module;
module.exports = function (name) {
if (module) return module;
module = {};
module.sayHi = function () {
return `Hi, ${name}`;
};
return module;
};
I'm a bit confused as to how to call sayHi after requireing utils.js.
// index.js
const utils = require("./utils")("Jim");
utils.sayHi();
I'm getting TypeError: utils.sayHi is not a function. What's the right way to call sayHi?

First you create a variable named module.
var module;
This does nothing because you are doing this in the scope of the module, so that variable already exists.
Then you assign a function to module.exports.
In another module, you import that function and call it.
The first line of that function says:
if (module) return module;
Is module a truthy value?
Yes. It is an object. If it wasn't, then assigning to module.exports would have throw an exception.
Consequently, you never overwrite module = {}; or assign the sayHi function to it.
Now look at the answer you referenced:
module.exports = function (app, db) {
var module = {};
It creates a new variable in the scope of the function so it doesn't conflict with the existing one.

Related

Imported module function in app.js does not have access to class instantiation or app.js variables. Javascript node

I have working code that fails when I try to split it into modules, this is a super simplified version to highlight the behavior I don't understand.
When app.js runs, there is a 'ReferenceError: elf1 is not defined'. I do not understand why func1 does not have access to elf1. I thought maybe changing the func1 to an arrow function away from a standard function would make func1 lexically scoped to app.js.
I realize that in App.js I can declare global.elf1 = new Elf() and then func1.js will have access. However, I don't understand why when an arrow function in a module is invoked within the app.js environment it doesn't have access to the app.js variable environment.
I'm sure this is simple and I'm overlooking some obvious behavior, I thought func1 being an arrow function would have access to app.js environment variables since it was invoked in app.js.
//App.js
let Elf = require('./class');
let func1 = require('./func');
var elf1 = new Elf('jim');
func1();
---------------------------------------
//class.js
class Elf{
constructor(name){
this.name = name;
}
shout(){
console.log(`my name is ${this.name}`);
}
}
module.exports = Elf;
----------------------------------
//func.js
let func1 = ()=>{
elf1.shout()
}
module.exports = func1;
func.js has no idea what elf1 is because it's outside of the module scope.
I would just pass in elf1 as a parameter into the func1 function.
//App.js
let Elf = require('./class');
let func1 = require('./func');
var elf1 = new Elf('jim');
func1(elf1);
//func.js
let func1 = (elf1)=>{
elf1.shout()
}
module.exports = func1;

Module functions appear undefined in outside scripts

This code tells me that the parse function is not a function:
const MyModule = require('./MyModule.js');
MyModule.parse('...');
In my module script it's defined like this:
MyModule = {};
MyModule.parse = function(data){
};
module.exports.MyModule = MyModule;
What am I doing wrong?
You have to understand that you are not exporting MyModule but an object (module.exports to be exact) with a member called MyModule (this is what you assigned to it).
If, in your code that requires MyModule, you console.log the result of your require, it will look like:
{ MyModule: {parse: [Function] } }
which is the module.exports object with a property (object) called MyModule that has a property (function) called parse.
So when you require you are getting the module.exports object that you assigned MyModule to and not just MyModule.
If you were to change your module.exports code to:
module.exports.X = MyModule;
Your code that required MyModule would then log:
{ X: {parse: [Function] } }
and you would call it as
MyModule.X.parse(...).
If you then changed your code to read
const MyFabulousModule = require('./MyModule');
you would then call it like:
MyFabulousModule.X.parse(...);
Finally, if you added another line to your module:
module.exports.Y = 4;
And then in your calling code added:
console.log(MyFabulouseModule.Y);
you would see the value 4 logged to the console.
Code:
MyModule.js
const MyModule = {};
MyModule.parse = function(data) {
console.log(data);
};
module.exports.X = MyModule;
module.exports.Y = 4;
test.js
const MyModule = require("./MyModule");
console.log(MyModule);
MyModule.X.parse("hello world");
console.log(MyModule.Y);
To run: node test.js
First of all, you need to add a keyword in definition object.
const MyModule = {};
And you export the object, which you appoint to constant, so you need to call the object from it like this:
MyModule.MyModule.parse('...')

Exporting a module Node.js [duplicate]

This question already has answers here:
In Node.js, how do I "include" functions from my other files?
(28 answers)
Closed 5 years ago.
Suppose I have a module, named mainModule.js, that has the statement.
var helper_formatModule = require('/formatModule.js');
Inside formatModule.js, I also have a statement,
var helper_handleSentences = require('/handleSentences.js');
If my original module, mainModule.js, needs functions defined in the handleSentences.js module would it be able to access them? I.e if it imported formatModule, a module that has handleSentences, does it have access to those? Or would I need to import the handleSentences.js module directly?
Only requiring a module A somewhere (in module B, for example) doesn't make the functions of A accessible in other modules. Normally, they're not even accessible in module B.
To access functions (or any values) from another module, that other module has to export them. The following scenario will not work:
// module-a.js
function firstFunction () {}
function secondFunction () {}
// module-b.js
var helper_handleSentences = require('/handleSentences.js');
// do something with 'helper_handleSentences'
module.exports = function (a) {
return helper_handleSentences(a);
}
As you can see, module-a.js doesn't export anything. Thus, the variable a holds the default export value, which is an empty object.
In your situation, you can either
1. require both modules in mainModule.js
// handleSentences.js
function doSomethingSecret () {
// this function can only be accessed in 'handleSentences.js'
}
function handleSentences () {
// this function can be accessed in any module that requires this module
doSomethingSecret();
}
module.exports = handleSentences;
// formatModule.js
var helper_handleSentences = require('/handleSentences.js');
// do something with 'helper_handleSentences'
module.exports = function (a) {
return helper_handleSentences(a);
};
// mainModule.js
var helper_handleSentences = require('/handleSentences.js');
var helper_formatModule = require('/formatModule.js');
// do something with 'helper_handleSentences' and 'helper_formatModule'
2. merge the exported values of both modules into one object
// handleSentences.js
function doSomethingSecret () {
// this function can only be accessed in 'handleSentences.js'
}
function handleSentences () {
// this function can be accessed in any module that requires this module
doSomethingSecret();
}
module.exports = handleSentences;
// formatModule.js
var helper_handleSentences = require('/handleSentences.js');
// do something with 'helper_handleSentences'
function formatModule (a) {
return helper_handleSentences(a);
};
module.exports = {
handleSentences: helper_handleSentences,
format: formatModule
};
// mainModule.js
var helper_formatModule = require('/formatModule.js');
// use both functions as methods
helper_formatModule.handleSentences();
helper_formatModule.format('...');

JavaScript augmented module pattern var name repeat

Can we reuse var name without overwriting its details in JavaScript.Taking below example of augmented module pattern
<script>
var Module = (function () {
// Module object
var module = {},
privateVariable = "Hello World";
function privateMethod() {
// ...
}
module.publicProperty = "Foobar";
module.publicMethod = function () {
//console.log( privateVariable );
return privateVariable;
};
return module;
})();
//Defining same name MODULE var again
var Module = (function (my) {
var newvar = 999;
my.anotherMethod = function () {
return newvar;
};
return my;
}(Module));
alert(Module.publicMethod());
//How this upper MODULE property is accessible ? Should be hide by
//next same name MODULE var?**
alert(Module.anotherMethod());
</script>
Above code is running perfectly fine and adding one more anotherMethod under MODULE but how it is still accessing initial module property. Defining var with same name (MODULE) shoudn't overwrite (remove) the upper module.
Defining var with same name (MODULE) shoudn't overwrite (remove) the upper module.
Yes, it should.
The global scope (or the function if you are inside a function) is scanned for var statements. Since you have two identical ones, the second one is ignored. MODULE is created in the global scope.
Then you run a function and then assign its return value to the MODULE.
Then you run another function, passing the current value of MODULE as an argument to it, then you assign the return value to MODULE.
A reference to the object created at var my = {} still exists in the scope of the second function, but the only reference to it from the global scope has been overwritten.

NodeJS: module.exports property is not a function

I have the following in a module file:
module.exports = {
myfunc: myfunc
};
var myfunc = function(callback){
callback(err,reply);
};
In an other file I got the reference to that module
var mymodule = require('./modules/mymodule');
mymodule.myfunc(function(err, reply){ ... });
When I call the mymodule.myfunc() I get an error saying "property 'myfunc' is not a function".
This happens only with exported functions. The same module exports some 'string' fields and these are working just fine.
When you assign module.exports, the myfunc function is still undefined. Try to assign it after declaring it:
var myfunc = function(callback){
callback(err,reply);
};
module.exports = {
myfunc: myfunc
};
To preserve your original ordering of module.exports at the top of your file, change your var myfunc initialization to a function myfunc declaration so that the latter is hoisted.
module.exports = {
myfunc: myfunc
};
function myfunc(callback){
callback(err,reply);
};
Declarations are hoisted, but initializations are not, which is why your original example did not work. w3schools has a practical description of JavaScript Hoisting.
Another scenario where i found this annoying issue was if explicitly imported only the function that my consumer needs
Say for example your exported modules looks like below
module.exports = {
func1 : async function func1(){}
func2 : async function func2(){
await this.func1(); // causes error : func1 is not a function
}
}
Now your consumer of above module looks like below:
const { func2 } = require('../theExportedModules');
//above only imports func2 but not its dependents and is not initialized
await func2(); //func2 called
Now func2() gets called from your consumer but func2() will not be able to call the func1() because it finds that func1() is not a function. Code breaks!
solution import entire modules:
const theExportedModules = require('../theExportedModules');
we could also just import func1 as well but then it would be an unused variable and we would get a warning for that.

Categories