2015-10-16 55 views
0

我有一个JavaScript代码,我需要通过其名称调用方法。方法名称在运行时生成。如何避免通过名称调用JavaScript方法eval()?

我用下面的代码来提取方法名和调用该方法的JavaScript方法的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); 
    } 
} 

是否有可能避免的eval()调用吗?

解决方案:

最后,我找到了我的问题以下解决方案。该方法接受参数,并且仅用于为需要由呼叫者提供的特定上下文:

/* 
* 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); 
    } 
} 
+0

您的代码不会调用该函数。 – Pointy

+0

'modelValue = model [methodName]()' – dandavis

+0

@Pointy:[yes yes will will](http://jsfiddle.net/nauzilus/8dtt5pxp/)。他在包含parens的'eval'中使用'modelField'变量。 (这并不是说奇怪的设置一个变量与parens首先,只是方法的名称就足够了)。 –

回答

4

你绝对不需要eval()

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

[ ]操作者通过访问属性包含的表达式的值。 ()运算符(如果可以调用它)会使检索到的值作为函数调用(如果它是函数)。

+0

他想调用'model [methodName]'还是'model [modelField]'?前者似乎更准确的基础上,如果条件。 –

+0

当你可以使用var method = model [methodName]; method.call && method();' –

+0

@StephanBijzitter:如果methodName使用'this',那么可能不起作用,所以要么显式调用它,要么保持方法附着在对象上。 – dandavis