I have a JavaScript code where I need to call a method by its name. The method name is generated during run-time.
I use the following code to extract the method name and call the method with the JavaScript method eval():
// e.g. modelField='getData()';
if (modelField.match("^[_a-zA-Z0-9.]+\\(")) {
try {
// test if method is defined by the model object...
methodName=modelField.substring(0,modelField.indexOf('('));
if ($.isFunction(model[methodName])) {
modelValue = eval('model.' + modelField);
}
} catch (err) {
console.error("Error calling gettermethod '"
+ modelField + "' -> " + err.message);
}
}
Is it possible to avoid the eval() call here?
Solution:
Finally I found the following solution for my problem. The method accepts parameters and is used only is a specific context which need to be provided by the caller:
/*
* helper method to call a model getter/setter method by name. The method
* expects theh funtion name including the parameters
*
* e.g. setValue('abc');
*
* Optional additional params can be set which will be added to the function
* call
*/
_executeFunctionByName = function(functionCall, context, params) {
var paramPos,methodName,args,fnparams,fn;
paramPos = functionCall.indexOf('(');
methodName = functionCall.substring(0, paramPos);
args = functionCall.substring(paramPos + 1).trim();
args = args.substring(0, args.indexOf(')')).trim();
// first split the params...
fnparams = args.split(",");
if (params) {
fnparams.push(params);
}
// clean param value ....
$.each(fnparams, function(index, _obj) {
// string literal ?
if (_obj.indexOf("'") === 0 || _obj.indexOf('"') === 0) {
fnparams[index] = _obj.substring(1, _obj.length - 1);
} else {
// param is treated as string literal
}
});
// find object
fn = context[methodName];
// is valid function?
if (typeof fn === "function") {
return fn.apply(context, fnparams);
}
}
modelValue=model[methodName]()modelFieldvariable in theevalwhich includes the parens. (That's not to say it isn't odd setting a variable with parens in the first place, just the method name would have been enough).