if I have a javascript file with the contents:
(function() {
return function (foo) {
return foo + "bar";
};
}());
is it possible to capture the return value from that file in a variable somehow? I'm assuming the function is returned to the auto instantiating parens and then garbage collected, but I'm not sure.
As an aside, I'm trying to expose a browserified collection of node modules to the window for testing purposes (I realize there are probably other methods for going about this, but I'm curious about this one).
Files that are included with browserify (or other CommonJS compatible system) can expose methods or values to the requiring file via module.exports. module.exports is returned from the require() statement.
Take this example:
index.js
var myClass = require("myClass");
myClass.js
module.exports = (function() {
return function (foo) {
return foo + "bar";
};
}());
index.js now has access to the function that is built in myClass.js and can use it as:
index.js
var myClass = require("myClass");
// expose the class to the global scope
window.myClass = myClass;
var result = myClass("foo ");
so the var result would have the value "foo bar".
Related
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.
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?
module is a plain JavaScript object with an exports property. exports is a plain JavaScript variable that happens to be set to module.exports.
At the end of your file, node.js will basically 'return' module.exports to the require function. A simplified way to view a JS file in Node could be this:
var module = { exports: {} };
var exports = module.exports;
// your code
return module.exports;
If you set a property on exports, like exports.a = 9;, that will set module.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 then exports and module.exports are the same object.
But if you set exports to something new, it will no longer be set to module.exports, so exports and module.exports are no longer the same object.
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
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
the above code is wrapped as IIFE(Immediately Invoked Function Expression) inside nodejs source code as follows:
(function (exports, require, module, __filename, __dirname) { //add by node
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
}).apply(); //add by node
return module.exports; //add by node
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
exports = function () {
console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
the output will be
[Function]
{}
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
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
the output will be
{ a: [Function] }
{ a: [Function] }
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 :)
Also, one things that may help to understand:
math.js
this.add = function (a, b) {
return a + b;
};
client.js
var math = require('./math');
console.log(math.add(2,2); // 4;
Great, in this case:
console.log(this === module.exports); // true
console.log(this === exports); // true
console.log(module.exports === exports); // true
Thus, by default, "this" is actually equals to module.exports.
However, if you change your implementation to:
math.js
var add = function (a, b) {
return a + b;
};
module.exports = {
add: add
};
In this case, it will work fine, however, "this" is not equal to module.exports anymore, because a new object was created.
console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
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
module.exports.add = function (a, b) {
return a + b;
};
Or:
math.js
exports.add = function (a, b) {
return a + b;
};
Rene's answer about the relationship between exports and module.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.
node does something like this:
module.exports = exports = {}
module.exports and exports refer to same object.
This is done just for convenience.
so instead of writing something like this
module.exports.PI = 3.14
we can write
exports.PI = 3.14
so it is ok to add a property to exports but assigning it to a different object is not ok
exports.add = function(){
.
.
}
↑ this is OK and same as module.exports.add = function(){...}
exports = function(){
.
.
}
↑ this is not ok and and empty object will be returned as module.exports still refers to {} and exports refer to different object.
There are two difference between module.exports and exports
When export a single class, variable or function from one module to another module, we use the module.exports. But export to multiple variables or functions from one module to another, we use exports.
module.exports is the object reference that gets returned from the require() calls. But exports is not returned by require().
see more details with examples >> link
As all answers posted above are well explained, I want to add something which I faced today.
When you export something using exports then you have to use it with variable. Like,
File1.js
exports.a = 5;
In another file
File2.js
const A = require("./File1.js");
console.log(A.a);
and using module.exports
File1.js
module.exports.a = 5;
In File2.js
const A = require("./File1.js");
console.log(A.a);
and default module.exports
File1.js
module.exports = 5;
in File2.js
const A = require("./File2.js");
console.log(A);
myTest.js
module.exports.get = function () {};
exports.put = function () {};
console.log(module.exports)
// output: { get: [Function], put: [Function] }
exports and module.exports are the same and a reference to the same object. You can add properties by both ways as per your convenience.
You can think of exports as a shortcut to module.exports within a
given module. In fact, exports is just a variable that gets
initialized to the value of module.exports before the module is
evaluated. That value is a reference to an object (empty object in
this case). This means that exports holds a reference to the same
object referenced by module.exports. It also means that by assigning
another value to exports it's no longer bound to module.exports.
This explanation from MDN is the most clear to me.
Basically, there is one object in memory which is referenced by 2 variables - exports and module.exports.
exports.a = 23
equals
module.exports = {a:23}
But,
exports = {a:23}
does not equal
module.exports = {a:23}
When you assign a new object to exports variable directly, then that variable does not refer to module.exports anymore.
I'm developing a Node.js application that contains a game engine, and I basically have this pattern in my engine:
A.js
var B = require('./B');
var A = module.exports = function () {
this.b = new B;
console.log(B.staticBar)
};
A.staticFoo = 'foo';
B.js
var A = require('./A');
var B = module.exports = function () {
console.log(A.staticFoo);
};
B.staticBar = 'bar';
So I want both A.staticFoo to be accessible in B.js and B.staticBar in A.js.
Any idea how to do that?
Thanks
EDIT : actually my static variables are config values, so another solution would be to group them into a config.js file and require that file in every other file, but I find it more elegant to define config variables directly as static members of related classes. Hope that's clear enough ;)
I would suggest separating your static state into a third module... By decoupling state from your module, you can operate either independently.
state.js
//state.js - changed by other modules...
module.exports = {
staticFoo: null,
staticBar: null
};
a.js
//a.js
var state = require('./state');
exports = module.exports = fnA;
...
function fnA() {
console.log(state.staticBar);
}
b.js
//b.js
var state = require('./state');
exports = module.exports = fnB;
...
function fnB() {
console.log(state.staticFoo);
}
Another example mentions something akin to dependency injection... given how modules work in JS, and that you can override for testing with proxyquire and the like, I tend to prefer the simpler requires structure over dealing with DI/IoC in JS as it muddles your project code.
I also like to do my requires, then my exports, then any methods within that module, usually just one method in a module.
It would depend on the architecture of your code. BUT, working with other people's code is always different of course.
The best choice is to separate your code into smaller module(s). If they're referencing each other it can challenging to build tests especially when the code grows.
OR
If that's not possible you could always remove coupling through the use of references.
B.js
var _A;
exports.setA = function(ref) {
_A = ref;
};
var B = exports.B = function () {
console.log(_A.staticFoo);
};
And use B.setA(A) to make sure B has a reference to use A.staticFoo
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));
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.