0

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);
    }
}
4
  • Your code won't call the function. Commented Oct 16, 2015 at 21:28
  • modelValue=model[methodName]() Commented Oct 16, 2015 at 21:29
  • @Pointy: yes it will. He's using the modelField variable in the eval which 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). Commented Oct 16, 2015 at 21:39
  • @DanielFlint ah, OK, so the parens are there in the variable. Commented Oct 16, 2015 at 21:40

1 Answer 1

4

You definitely don't need eval():

    if ($.isFunction(model[methodName])) {
        modelValue = model[modelField]();
    } 

The [ ] operator accesses properties via the value of the contained expression. The () operator (if you can call it that) causes the value retrieved to be called as a function (if it is a function).

Sign up to request clarification or add additional context in comments.

8 Comments

does he want to call model[methodName] or model[modelField]? Former seems more accurate based on the if condition.
no need for jQuery when you can use var method = model[methodName]; method.call && method();
@StephanBijzitter: that might not work if methodName uses this, so either call it explicitly or keep the method attached to the object.
@NG. I don't know; I would assume that if the code puts a value in a variable called "methodName" that that would be the name of the method :) I could be wrong of course. The point is that there's no need for eval().
Thanks for your answer. But what if I need also to pass parameters by name: e.g. modelField="getData('firstname',42)"; how can I pass these params 'firstname' and 42?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.