How do I access/create a sub module based on the module pattern?
I would like to have the ability to access methods from sub modules in my Modules.js main file.
Module.js
var Module = (function() {
function A(){
console.log("Module: A");
B();
};
function B(){
console.log("Module: B");
Module.Utils.C(); /* Here is the problem */
};
return {
A:A,
B:B
}
} ());
$(function() {
Module.A();
});
Module.Utils.js
var Module = Module ? Module : {};
Module.Utils = (function() {
var settings = {
x : 1,
y : 2
};
function C(){
console.log("Module.Utils: C");
};
function D(){
console.log("Module.Utils: D");
};
return {
C:C,
D:D
}
}());
There's nothing wrong with your approach, provided:
You load the sub-module script after the module script
You do not attempt to access the sub-module script before it is loaded
You're OK with making your primary module dependent on the existence of the sub-module. (I'm not so sure this is a good idea.)
Side-issue
Your code currently has a syntax error on the following line:
var Module.Utils = (function() {
There should be no var keyword preceding the assignment.
Example Code
Here's a simplified version of your code -- stripped to show only the methods I'm invoking -- that demonstrates that your approach works:
var Module = (function() {
function B() {
console.log("Module: B");
Module.Utils.C(); /* accessing submodule public methods */
};
return {
B: B
};
})();
var Module = Module || {};
Module.Utils = (function() {
function C() {
console.log("Module.Utils: C");
};
return {
C: C
}
})();
Module.B();
Output:
Module: B
Module.Utils: C
You should look into using an actual module framework like RequireJS.
A "submodule" would then just be a module located at module/utils, and your module module would require it as a dependency, which RequireJS would take care of resolving for you.
Related
Say I have a module with two functions with one depending on the other:
// example.js
function A() {
return "hello";
}
function B() {
return A();
}
module.exports.B = B;
Can I use rewire to mock the call to A() in B()?
// example.test.js
var assert = require('chai').assert,
rewire = require('rewire'),
example = rewire('./example.js');
example.__set__({
A: function( return 'goodbye';),
});
describe('test B in example.js', function() {
it('should return "goodbye"', function() {
assert.strictEqual(example.B(), 'goodbye');
});
});
Yes, this does work. I'm not sure what solved the problem exactly. Previously I was exporting the dependent function as part of a function prototype (e.g. function.prototype.dependentFunction = function() { };) and somehow this was messing with rewire. I redefined my function by declaring/defining it first and then attaching it to the model:
function dependentFunction() { ... }
exportedObject.prototype.dependentFunction = dependentFunction();
Doing this fixed my problems.
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 was reading javascript Modular pattern from this url http://viralpatel.net/blogs/javascript-module-pattern/ and
http://www.codeproject.com/Articles/247241/Javascript-Module-Pattern
and some time confusion arise in my mind. so here i am putting things where i get some confusion. please help me to understand all.
Question 1
see the below code. all private variable and function declared in module with var keyword. here pub object also declared with var keyword.
it means pub is private. so when pub is private then how people can call pub related function from out side like below code
calling syntax
CalcModule.add(2,10);
CalcModule.add(5,15);
CalcModule = (function(){
var pub = {};
var mem = new Array(); //private variable
var storeInMemory = function(val) { //private function
mem.push(val);
};
pub.add = function(a, b) {
var result = a + b;
storeInMemory(result); //call to private function
return result;
};
pub.sub = function(a, b) {
var result = a - b;
storeInMemory(result); //call to private function
return result;
};
pub.retrieveFromMemory = function() {
return mem.pop();
};
return pub;
})();
CalcModule.add(2,10);
CalcModule.add(5,15);
console.log(CalcModule.retrieveFromMemory()); //outputs 20
console.log(CalcModule.retrieveFromMemory()); //outputs 12
Question 2
Separating Module across different JS files: Augmentation
file1.js
var CalcModule = (function($, pub){
//jQuery will still be available via $
var mem = new Array(); //private variable
pub.storeInMemory = function(val){
mem.push(val);
};
pub.retrieveFromMemory = function(){
return mem.pop();
};
return pub;
})(jQuery, CalcModule || {});
file2.js
var CalcModule = (function($, pub){
//jQuery will still be available via $
pub.add = function(a,b){
var result = a + b;
pub.storeInMemory(result);
return result;
};
pub.sub = function(a,b){
var result = a - b;
pub.storeInMemory(result);
return result;
};
return pub;
}(jQuery, CalcModule || {}));
see this function($, pub) syntax. why dollar sign is there and why pub need to pass there.
Question 3
what is the difference between module Augmentation and sub module ?
Question 4
Extending existing module module
var Module1 = ( function (oldModule) {
var
//assigning oldmodule in to a local variable.
parent = oldModule;
//overriding the existing privileged method.
parent.privilegedMethod = function ( ){
//do something different by overriding the old method.
};
//private method accessing privileged method of parent module.
var privateMethod2 = function ( ) {
parent.privilegedMethod();//can access privileged method of Module
parent.publicMethod1(); //can access public method of Module
}
return {
newMethod : function ( ) {
///do something for this brand new module.
///use some functionality of parent module.
/// parent.privilegedMethod( );
}
};
} )(Module);//
Module object is the existing module that I want to extend.
how anyone can understand the above code extend the module. just by this syntax (Module) ?
Question 5
if we write module in 5 separate js file then which file we need load first. what will be the order of loading those module related s file ?
Answer 1
Because at the end it's returning pub so you'll have access to all its methods
CalcModule = (function(){ return pub; }());
CalcModules === pub
Answer 2
function($, pub)
This is the declaration of the anonymous function that is called at the end of the code
Here we have the effective call passing jQuery and your module
(jQuery, CalcModule || {}));
N.B.
We are passing jQuery as first parameter and CalcModule as second only if exist otherwise an empty object (CalcModule OR {}).
The first time the function is called CalcModule doesn't exist and so you'll end up passing an empty object, the second time CalcModule exist because has been created by the previous call.
This is done to make it order agnostic.
So we can deduce
First Call
$ === jQuery
pub === {}
Second and next Calls
$ === jQuery
pub === CalcModule
You have to pass CalcModule to the function so it can be expanded.
This
(function($, pub){...}(jQuery, CalcModule || {}));
is exactly equal to this
var anonFunc = function($, pub){...};
anonfunc(jQuery, CalcModule || {});
Answer 3
Augmentation: you are adding functionality to the same module
pub.add = function(a,b){}
pub.sub = function(a,b){}
Sub-Module: you are adding a module to another module
subModule.add = function(a,b){}
subModule.sub = function(a,b){}
pub.subModule = function(a,b){ return mySubModule; }
Answer 4
You are passing Module but it's creating a brand new module that can USE the Module you have passed, this is more like a sort of Inheritance than Augmentation
Answer 5
Depends, but generally it's indifferent because you're just declaring the functionalities of your Module.
The only case where you need to respect an order is when a functionality construction depends on another functionality of the module.
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?