I have an application with three pages (which are single-page interfaces). The pages have similar but not identical functionality.
So I want to have javascript-modules that provide the common functionality. Then each page may customize/overwrite parts of the common functionality.
I'm using backbone.js, so what I do is:
At the moment I store my modules in a module-container similar to this: https://stackoverflow.com/a/9426071 Each module has an optional init() function that is executed by my main init() function.
Example:
I have a file called results.js. It defines the common Model/Collection/View of search-results. In its init() function everything is instanciated, but this function is not yet called:
var resultView = new ResultView()
Then I include myApp.js, and parts of the View are overwritten.
Now I want to switch to require.js instead of my own module-container, and wonder how to organize my code.
I could either instanciate all models/views etc. in myApp.js instead of the init() function of each module. This would mean to have a lot of repetitive code.
Or I could stick to each module having its init() function, and call those init() functions in myApp.js. I don't like this because I would have to explicitly write down my modules three times for each of my three pages:
require(['module1', 'module2', 'module3', ...],
function(module1, module2, module3, ...) {
var init = function() {
module1.init();
module2.init();
module3.init();
...
}
return {init: init};
}
);
For 10 modules plus a number of libraries this is not nice and DRY. Is there any way to access (loop over) all modules that require.js holds?
Or am I missing something, should I structure my code in a different way?
Any hints/thoughts are welcome,
Michael
As discussed in the comments above, you can avoid having to explicitly reference the parameters of the function by looping over them using the arguments
object inside the function body. So:
require(['module1', 'module2', 'module3', ..., 'moduleN'],
function(module1, module2, module3, ..., moduleN) {
var init = function() {
module1.init();
module2.init();
module3.init();
...
moduleN.init();
};
return {init: init};
});
Becomes:
require(['module1', 'module2', 'module3', ..., 'moduleN'],
function() {
var args = arguments;
var init = function() {
var module;
for (module in args) {
if (args.hasOwnProperty(module) && typeof module.init === 'function') {
module.init.call(this);
}
}
};
return {init: init};
});
I added in a hasOwnProperty()
check inside the for in
loop because, for a number of reasons, it's good practice. Also, you'll see the explicit check for init
being a function before attempting to call it.
The reason for var args = arguments
is so you can reference it from the inner function - otherwise you would be referencing the arguments passed to init()
, which is not what you want.
As and aside, on an architectural level, I think the project structure you've described works incredibly well - I use it on a lot of very big projects and it's never let me down. Require.js is awesome! :)