Calling Arbitrary Function With Javascript 'apply'
Solution 1:
this
does not make sense in your context.
You have to define the functions in the global scope, or on another namespace, and use window
, or the name of that namespace instead of this
.
// Globally: functionmodules(method, args) {
window[method].apply(null, args);
}
modules('overview', ['test1', 'test2']);
// Locally:var namespace = {};
namespace.overview = overview; // Defined previouslyfunctionmodules(method, args) {
namespace[method].apply(null, args);
}
modules('overview', ['test1', 'test2']);
If you want to use this method locally, without predefining a namespace, there is no other option than using eval
:
// Locallyfunctionmodules(method, args) {
eval(method).apply(null, args);
}
modules('overview', ['test1', 'test2']);
Expanding the implementation:
If you want to handle unknown functions without throwing errors, use:
functionmodules(method, args) {
var ns = window; // or namespace (method 2) or eval(method) (method 3)if (ns.hasOwnProperty(method) && typeof ns.method === 'function') {
ns.apply(null, args);
} else {
console.log(' Unknown method: ' + method);
}
}
Demos
- Global: http://jsfiddle.net/QFpRc/4/
- Local + namespace: http://jsfiddle.net/QFpRc/3/
- Local + eval: http://jsfiddle.net/QFpRc/2/
Solution 2:
Your reference to this
in the modules
function declaration points to the modules
objects. Since modules
doesn't have an 'overview' property, there is no 'overview' method to invoke. As @Rob W stated, you could explicitly reference the global window
object, where your functions are defined, or you could define your own object:
var myObj = {
overview: function(arg1, arg2, arg3) {
console.info('arg1 is ' + arg1);
console.info('arg2 is ' + arg2);
console.info('arg3 is ' + arg3);
},
modules: function(method, args) {
this[method].apply(null, args);
}
};
myObj.modules('overview', newArray('test1', 'test2'));
See http://jsfiddle.net/QFpRc/1/ for a live example.
Solution 3:
Your code will perform faster if you used Function.prototype.bind instead of passing parameters thru a proxy function. Bind will save processing time and memory by applying the context and routing arguments before the actual function call
functionoverview(arg1,arg2,arg3){
console.info('arg1 is ' + arg1);
console.info('arg2 is ' + arg2);
console.info('arg3 is ' + (arg3 || this.foo));
}
var context = { foo:'bar' };
var contextOverview = overview.bind(context);
var modOverview = function(){}.apply.bind(overview.bind(context), context);
modOerview(['test1','test1'])
A closure'd variant might look something like:
var importModule = (function(){
var mods = {
overview:function(arg1,arg2,arg3){
console.info('arg1 is ' + arg1);
console.info('arg2 is ' + arg2);
console.info('arg3 is ' + (arg3 || this.foo()));
console.warn('This context is ' + this);
}
};
returnfunctionexportMod(name, context){
var mod = mods[name].bind(context);
return mod.apply.bind(mod,null);
}
})();
var myContext = (function(){
var foo = 'bar';
var overview;
var context = {
overview:function(){ returnoverview() },
foo:function(){ return foo },
toString:function(){ return'my context!' }
};
overview = importModule('overview', context);
return context;
})();
myContext.overview(['test1','test2']);
That being said, why don't you just call the function like normal? I mean, if you know the context and the function name.... .. .
Post a Comment for "Calling Arbitrary Function With Javascript 'apply'"