I am a c++ programmer at heart and I'm currently being thrown into the deep end with javascript and asked to swim very quick. I am using browserify so I am able to use the require function that node.js uses to get get access to code in other files. Now everything I have done seems to be working fine, I am just unsure that I am doing it correctly.
//a.js
module.exports = function(){
alert("hello world");
}
//b.js
var myClass = new MyClass();
module.exports = myClass;
//c.js
var a = require("./a.js");
a();
var b = require(./b.js");
b.prototype.test = 555;
//d.js
function () {
var a = require("./a.js");
a();
var b = require(./b.js");
assert(b.test === 555);
}
function () { // duplicated require called inside same file but different function
var a = require("./a.js");
a();
}
So in every function and every file I want to use a.js do I have to put the require call? Seems like it will get a bit convoluted. Is there a better way to do this? Also assuming that c.js is ran before d.js will the assert pass or does it result in a copy being created of myClass so the objects are different between C and D?
Thanks for any help.
The result of require function is cached, so it would be the same only within a single process.
By the way, I cannot understand why you require a.js twice. Why not just do
//d.js
var a = require("./a.js");
function () {
a();
var b = require("./b.js");
assert(b.test === 555); // success!
}
function () { // no dupes!
a();
}
Related
js files index.js and utils.js
I have tried to do the module export solution with no luck.
To call a function in utils.js from index.js I write a the function in utils as
export.functioname = function(parms) {
...
};
If i want to call the same function internally from utils.js i can do it i have to write another identical function as:
var functionname (parms) {
...
}
How can i get around this and only have one function to be called externally and internally?
You can use:
var yourfunction = function(param){
console.log(param);
}
exports.yourfunction = yourfunction;
yourfunction("Works");
Which prints:
"Works"
Functions can be saved to variables
var moo = function(parms) {};
export.functioname = moo;
or
function moo(parms) {};
export.functioname = moo;
works aswell because of js closures
I've been running into this issue lately and am looking for a good solution.
Below is the basic setup.
In c.js, a is an empty object. Currently I got around this by putting the var a=require('./a.js') inside the function (cFunction) that needs access to module a's methods. But is that the best way to go about this?
Thanks,
David
main.js
var a = require('./a.js');
a.js
module.exports = (function() {
var b = require('./b.js');
function aFunction() {
console.log("aFunction");
}
return {
aFunction: aFunction
};
})();
b.js
module.exports = (function(){
var c = require('./c.js');
function bFunction(){
console.log('bFunction');
}
return {
bFunction: bFunction
};
})();
c.js
module.exports = (function(){
var a = require('./a.js');
console.log(a); //empty object
function cFunction(){
a.aFunction(); //undefined
console.log('cFunction');
}
return {
cFunction: cFunction
};
})();
So the first one being something like:
myFile.js
var name = "Peter";
module.exports.sayHello = function () {
console.log('Hello ' + name);
}
And the second one
myFile.js
module.exports = function () {
var name = 'Mary';
function sayHello () {
console.log('Hello ' + name);
}
return {
sayHello : sayHello
};
}();
Essentially it's the same thing right? If not, what's the difference and what's the pros and cons of each method?
Why do we need modules?
When you have a code like this:
// module 1
var a = 1;
var x = function (){
return a;
};
// module 2
var a = 2; // duplicated variable declaration
var y = function (){
return a;
};
// main
console.log(x()); // BUG: this should read value from module 1 instead of module 2
console.log(y());
It will lead to error, since the a variable was already taken by the first module. You need to define modules somehow.
Using a prefix
By old-style procedural programming you would add a prefix to separate modules:
// module 1
var m1_a = 1;
var m1_x = function (){
return m1_a;
};
// module 2
var m2_a = 2;
var m2_y = function (){
return m2_a;
};
// main
console.log(m1_x());
console.log(m2_y());
But this makes the code less readable.
Using closures
By javascript you have closures, which make things a little bit easier:
// module 1
var x = (function (){
var a = 1;
var x = function (){
return a;
};
return x;
})();
// module 2
var y = (function (){
var a = 2;
var y = function (){
return a;
};
return y;
})();
// main
console.log(x());
console.log(y());
But still you have different modules in a single file, so that file will be really big and hard to maintain.
Using the node.js module loader
By node.js you can move the code of different modules to separate files, so it will be easy to maintain the code of different modules, since you will be able to find the relevant part of the code much faster:
m1.js
var a = 1;
var x = function (){
return a;
};
module.exports = x;
m2.js
var a = 2;
var y = function (){
return a;
};
module.exports = y;
main.js
var x = require("m1");
var y = require("m2");
console.log(x());
console.log(y());
You can do the same in the browser
The simplest node.js style browser module loader I could come up with so far, is this:
var cache = {};
function require(name){
if (name in cache)
return cache[name];
var uri = "./" + name + ".js";
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, false);
xhr.send(null);
var moduleCode = xhr.responseText;
var fn = new Function("module", moduleCode);
var module = {};
fn(module);
cache[name] = module.exports;
return cache[name];
};
Ofc. it is much safer to use browserify, webpack, require.js and other more sophisticated libs, I just wanted to show you, it is not that hard to write a loader.
What did we learn from all of this?
Both node.js modules and closures are for modularization. You should not mix them, since they solve the same problem, and mixing them will lead only to confusion!
For me it's the same thing.
Maybe the first example is more common.
You can use both, according to the rest of your code.
Yes they are basically the same. You just don't need the verbosity of the second example.
In the first example you are adding a named property to the already existing module.exports object injected by node.js, in the second example you are overriding the original object - there is no difference for the consuming end.
Lets go to the basics of module mechanism in NodeJS. For every JS
file the ground reality is which happens on the top of file:
var exports = module.exports = {};
Whenever we try to fetch the import it retrieves module.exports only
If we do both in Js file
exports.key = "key1" and module.exports = {key : "VAL"}
only the module.exports is fetched during the import according to the rule.
Now coming back to your question Adding module.exports.sayHello will
add the reference to the {} which is common with exports variable too.
However if you do
module.exports = function () {} // some function
it breaks the chain and it is only assigned to module.exports and not
exports variable.
This is why if we add any key to exports variable is retrieved via
module.exports during import! Hope it clarifies!
A very good article on this https://www.sitepoint.com/understanding-module-exports-exports-node-js/
I'm learning node.js and interested in is there any difference between following two cases.
I.E. I have some variable myvar (like db connection or just constant string "test") that needed to be passed in many modules and submodules.
First case.
Create modules, that accept that variable as a param:
submodule.js:
var option
, submodule = {};
submodule.func = function(){
...
var something = option;
...
}
module.exports = function(opts){
option = opts;
return submodule;
}
module1.js:
var option
, submodule
, module1 = {};
module1.func = function(){
...
submodule.func();
...
var something = option;
...
}
module.exports = function(opts){
option = opts;
submodule = require('./submodule')(opts);
return module1;
}
In this case if submodule is used in several modules with same myvar value (i.e. 2 modules) submodule's module.exports function will be called 2 times. In node.js mans it said that "Modules are cached after the first time they are loaded". And I can't understand is this module cached or not.
Another case:
That myvar can be passed as parameter to module functions. So code will look like:
submodule.js:
function func(option){
...
var something = option;
...
};
exports.func = func;
module1.js:
var submodule = require('./submodule');
function func(option){
...
submodule.func(option);
...
var something = option;
...
};
exports.func = func;
So the question is:
Is there any difference between this two cases or they are same?
I'm not exactly sure what you're asking here, but if you need to pass values into your modules you should make sure to export functions that accept parameters. When they say that a module is cached, it means that your module is only initialized once. Think of your module as an object:
var a = 1;
var b = 2;
console.log("init!");
module.exports.test = function(){
console.log("this is a function!");
}
Here, a, b, and the first log will run only once. This is when the module is requested and is then cached. When you do a
var example = require("module")
If it was never created it'll initialize a, b, and do the log message. If it was already created it will just give you a reference to what you exported. Each time you call:
example.test()
It will output: this is a function!
But you will NOT get the a, b, and the first log run again.
Think of all statements not exported as private static variables of that object.
Here is another fully working example:
app.js
var s = require("./sample");
var y = require("./sample");
s.test();
y.test();
s.test();
console.log("finished");
sample.js
var a = 1;
var b = 2;
console.log("init!");
function test() {
console.log("here! " + a);
a++;
}
exports.test = test;
This all outputs:
init!
here! 1
here! 2
here! 3
finished
Does this help at all?
I'm trying to do the following:
//Code under test
function Foo() {
this.do_something_interesting = function() {
var dependency = new CanYouMockMe();
if(dependency.i_want_stubbed() === true) {
//do stuff based on condition
} else {
//do stuff if false
}
}
}
//Test Code
describe("Foo", function () {
it("should do something if the dependency returns true", function () {
var foo = new Foo();
//how do I stub and/or redefine the "i_want_stubbed" method here?
var result_if_true = foo.do_something_interesting();
expect(true).toEqual(result_if_true);
});
});
The gist of the question is: how do I redefine an instance method in javascript?
Your Foo.do_something_interesting demonstrates a common feature of untestable / hard-to-test code, namely that it uses "new" and has a dependency that is not passed-in. Ideally, you would have:
do_something_interesting = function(dependency) {
// ...
}
In the above, it is much easier to replace your dependency with a Mock. That said, you can use the properties of a given instance or of the prototype to replace bits and pieces. For example:
Foo.prototype.CanYouMockMe = function() {};
Foo.prototype.CanYouMockMe.prototype.i_want_stubbed = function() {
console.log("I'm a stub");
};
You can save the properties before you overwrite them, and then restore those properties after your test case, to make it possible to run multiple tests in isolation of each other. That said, making dependencies explicit is a big win both for testability and for making your APIs more flexible / configurable.