如何将字符串转换为 JavaScript 函数调用?

IT技术 javascript function
2021-01-19 19:23:49

我得到了一个像这样的字符串:

settings.functionName + '(' + t.parentNode.id + ')';

我想转换成这样的函数调用:

clickedOnItem(IdofParent);

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

传奇:

settings.functionName = clickedOnItem

t.parentNode.id = IdofParent
6个回答

鉴于我讨厌 eval,而且我并不孤单

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

编辑:回复@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);
}
鉴于最初的问题,我认为“if(typeof...”代码不正确。只需调用 window[settings.functionName](t.parentNode.id)。如果函数没有,你会得到一个 TypeError存在,这比默默地吞下问题而不打电话更好。
2021-03-20 19:23:49
@uptownhrwindow.settings.functionName确实如此。window[window.settings.functionName]现在。在 javascript 中,对象成员可以像访问数组一样通过字符串访问。假设你的函数是在全局范围内声明的,它就变成了 window 对象中的一个函数。您可以使用字符串调用它。
2021-03-23 19:23:49
但是如果函数不在全局(窗口)范围内呢?
2021-03-28 19:23:49
似乎如果没有“我讨厌评估”,那在政治上就会是错误的。node.js 和表达式字符串来自数据库的最佳方法是什么?
2021-04-01 19:23:49
请参阅我的 awnser 以获取从字符串中检索函数的通用方法,即使在多个闭包中也是如此。如果您想在 DOM 属性内注册回调,这是理想的选择。
2021-04-07 19:23:49
window[settings.functionName](t.parentNode.id);

不需要 eval()

但是在关闭代码中不起作用。 (function(){})();
2021-03-21 19:23:49
好的。当然,这是假设该函数没有在不同的范围内声明,但即使如此,我也可以想象您可以在该范围内执行此操作...
2021-03-28 19:23:49
很高兴看到另一个人尽可能避免使用 eval。
2021-03-28 19:23:49
工作得很好。甚至比 eval 函数调用使用更少的代码。
2021-03-31 19:23:49
如果所需的函数在全局范围内,则它起作用,如果不在,则用函数的范围替换 window 。
2021-04-10 19:23:49

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

// 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]];
}

希望它可以帮助一些人。

+1 使其适用于任何范围。我正在使用 TypeScript,并设置“scope=this”来访问我的类中的函数。工作完美!
2021-03-11 19:23:49
为我工作。感谢 NGauthier
2021-03-18 19:23:49
很好,我使用了多个作用域的 WinJS.Namespace.define(),多亏了你,我能够从它动态调用随机函数。
2021-04-05 19:23:49
花了将近半天的时间在谷歌上搜索答案。这是一个绝妙的解决方案!+1
2021-04-06 19:23:49

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

eval(settings.functionName + '(' + t.parentNode.id + ')');
看机器回答。
2021-03-15 19:23:49
Eval 不是“邪恶的”,但它可能很慢而且肯定是不安全的。
2021-03-17 19:23:49
你们是一群跟随一句押韵的名言的追随者。如果你问这些“eval 是邪恶的”人中的任何一个,为什么它实际上是邪恶的,而不让他们匆忙去谷歌搜索,你将得不到答案。这是绵羊编程的经典例子。如果你不明白它,保持沉默和研究。
2021-03-22 19:23:49
我可以反对它在适当的情况下使用 eval 。这里不需要评估。最好将函数作为对象的属性来查找。Eval动作缓慢,有点像用大锤打苍蝇。
2021-03-26 19:23:49
eval 是一个常见的习语。如果你不喜欢它,你可能会讨厌 Javascript。恕我直言, eval 是这里的正确答案。如果您删除 if-typedef 检查,机器的答案是可以的,但它会无缘无故地添加代码。如果您传递的字符串有问题,那么在任何一种情况下您都会遇到问题。
2021-04-08 19:23:49

eval() 是您需要执行此操作的函数,但我建议您尝试其中之一以尽量减少 eval 的使用。希望其中之一对您有意义。

存储函数

将函数存储为函数,而不是字符串,稍后将其用作函数。您实际存储函数的位置取决于您。

var funcForLater = clickedOnItem;

// later is now
funcForLater(t.parentNode.id);

或者

someObject.funcForLater = clickedOnItem;    
// later is now    
(someObject.funcForLater)(t.parentNode.id);

存储函数名称

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

(eval(settings.functionName))(t.parentNode.id);

这最大限度地减少了您必须构建和评估的 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);

(小注:如果您在这里使用了语法,itemActions[actionName](t.parentNode.id);则该函数将作为 的方法被调用itemActions。)

我真的很喜欢字典处理程序方法 - 对我来说效果很好 - 谢谢。
2021-03-21 19:23:49