如何将String转换为JavaScript函数调用?

Spo*_*com 255 javascript function

我有一个字符串:

settings.functionName + '(' + t.parentNode.id + ')';
Run Code Online (Sandbox Code Playgroud)

我想要转换成函数调用,如下所示:

clickedOnItem(IdofParent);
Run Code Online (Sandbox Code Playgroud)

这当然必须在JavaScript中完成.当我发出警报时settings.functionName + '(' + t.parentNode.id + ')';,似乎可以使一切正常.我只需要调用它将转换成的函数.

传说:

settings.functionName = clickedOnItem

t.parentNode.id = IdofParent
Run Code Online (Sandbox Code Playgroud)

Pat*_*and 358

看到我讨厌eval,而我并不孤单:

var fn = window[settings.functionName];
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}
Run Code Online (Sandbox Code Playgroud)

编辑:回复@Mahan的评论:在这个特殊情况下,settings.functionName会是"clickedOnItem".这将在运行时转换var fn = window[settings.functionName];var fn = window["clickedOnItem"],将获得对它的引用function clickedOnItem (nodeId) {}.一旦我们在变量中引用了一个函数,我们就可以通过"调用变量"调用这个函数,即fn(t.parentNode.id)等于clickedOnItem(t.parentNode.id),这就是OP想要的.

更完整的例子:

/* Somewhere: */
window.settings = {
  /* [..] Other settings */
  functionName: 'clickedOnItem'
  /* , [..] More settings */
};

/* Later */
function clickedOnItem (nodeId) {
  /* Some cool event handling code here */
}

/* Even later */
var fn = window[settings.functionName]; 
/* note that settings.functionName could also be written
   as window.settings.functionName. In this case, we use the fact that window
   is the implied scope of global variables. */
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}
Run Code Online (Sandbox Code Playgroud)

  • 但是如果函数不在全局(窗口)范围内怎么办? (23认同)
  • 鉴于原始问题,我认为"if(typeof ..."代码不正确.只需调用window [settings.functionName](t.parentNode.id).如果函数没有,你会得到一个TypeError存在,这比悄无声息地吞下这个问题并且什么都不召唤更好. (3认同)
  • 似乎如果没有“我讨厌评估”,那在政治上是错误的。node.js 和表达式字符串来自数据库的最佳方法是什么? (2认同)

Fab*_*ger 71

window[settings.functionName](t.parentNode.id);
Run Code Online (Sandbox Code Playgroud)

不需要eval()

  • 如果所需的函数在全局范围内,则它可以工作,如果没有,则通过函数的范围替换窗口. (5认同)
  • 很高兴看到另一个可能会避免评估的家伙. (2认同)

NGa*_*ier 67

这是一种更通用的方法来做同样的事情,同时支持范围:

// Get function from string, with or without scopes (by Nicolas Gauthier)
window.getFunctionFromString = function(string)
{
    var scope = window;
    var scopeSplit = string.split('.');
    for (i = 0; i < scopeSplit.length - 1; i++)
    {
        scope = scope[scopeSplit[i]];

        if (scope == undefined) return;
    }

    return scope[scopeSplit[scopeSplit.length - 1]];
}
Run Code Online (Sandbox Code Playgroud)

希望它可以帮助一些人.


And*_*are 14

JavaScript有一个eval函数来计算字符串并将其作为代码执行:

eval(settings.functionName + '(' + t.parentNode.id + ')');
Run Code Online (Sandbox Code Playgroud)

  • 你们是一群追随者,只是押韵.如果你问这些"eval is evil"中的任何一个人为什么它们实际上是邪恶的而没有他们匆匆走向谷歌,你将得不到答案.这是绵羊编程的典型例子.如果你不理解它,保持沉默和研究. (16认同)
  • 我可以在适当的情况下使用eval进行downvote.这里不需要评估.最好将函数作为对象的属性来查找.Eval很慢,有点像用大锤拍苍蝇. (13认同)
  • eval是一种常见的习语.如果你不喜欢它,你可能会讨厌一般的Javascript.恕我直言,eval是正确答案.如果删除if-typedef检查,机器的答案是可以的,但它无缘无故地添加代码.如果您传递的字符串出现问题,则在任一情况下都会出现问题. (3认同)
  • Eval不是"邪恶的",但它可能很慢并且肯定是不安全的. (2认同)

Jes*_*kan 13

eval()是你需要做的功能,但我建议尝试其中一个来最小化eval的使用.希望其中一个对你有意义.

存储功能

将函数存储为函数而不是字符串,稍后将其用作函数.实际存储功能的地方取决于您.

var funcForLater = clickedOnItem;

// later is now
funcForLater(t.parentNode.id);
Run Code Online (Sandbox Code Playgroud)

要么

someObject.funcForLater = clickedOnItem;    
// later is now    
(someObject.funcForLater)(t.parentNode.id);
Run Code Online (Sandbox Code Playgroud)

存储功能名称

即使您必须将函数名称存储为字符串,也可以通过执行操作来最小化复杂性

(eval(settings.functionName))(t.parentNode.id);
Run Code Online (Sandbox Code Playgroud)

这可以最大限度地减少你必须构建和评估的Javascript数量.

处理程序字典

将您可能需要的所有动作函数放入对象中,并使用字符串将其称为字典样式.

// global
itemActions = { click: clickedOnItem, rightClick: rightClickedOnItem /* etc */ };

// Later...
var actionName = "click"; // Or wherever you got the action name
var actionToDo = itemActions[actionName];
actionToDo(t.parentNode.id);
Run Code Online (Sandbox Code Playgroud)

(次要注意:如果在这里您使用了语法,itemActions[actionName](t.parentNode.id);那么该函数将被称为方法itemActions.)


nsi*_*nov 9

虽然我喜欢第一个答案并且我讨厌eval,但我想补充说还有另一种方法(类似于eval)所以如果你可以绕过它并且不使用它,你最好这样做.但在某些情况下,您可能希望在某个ajax调用之前或之后调用一些javascript代码,如果您在自定义属性而不是ajax中使用此代码,则可以使用此代码:

    var executeBefore = $(el).attr("data-execute-before-ajax");
    if (executeBefore != "") {
        var fn = new Function(executeBefore);
        fn();
    }
Run Code Online (Sandbox Code Playgroud)

或者最终将其存储在函数缓存中,如果您可能需要多次调用它.

再次 - 如果您有其他方法,请不要使用eval或此方法.


Gum*_*mbo 8

如果settings.functionName已经是一个函数,你可以这样做:

settings.functionName(t.parentNode.id);
Run Code Online (Sandbox Code Playgroud)

否则,如果settings.functionName只是函数的名称,这也应该有效:

if (typeof window[settings.functionName] == "function") {
    window[settings.functionName](t.parentNode.id);
}
Run Code Online (Sandbox Code Playgroud)


B R*_*d C 7

我希望能够将函数名称作为字符串,调用它,并将参数传递给函数.我无法得到这个问题的选定答案,但这个答案完全解释了,这是一个简短的演示.

function test_function(argument)    {
    alert('This function ' + argument); 
}

functionName = 'test_function';

window[functionName]('works!');
Run Code Online (Sandbox Code Playgroud)

这也适用于多个参数.