2015-10-16 62 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