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

我得到了一个字符串:

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

我想翻译成一个函数调用,像这样:

clickedOnItem(IdofParent);

当然,这必须用JavaScript来完成。当我在settings.functionName + '(' + t.parentNode.id + ')';上做一个警告时,它似乎得到了正确的一切。我只需要调用它转换成的函数。

传说:

settings.functionName = clickedOnItem


t.parentNode.id = IdofParent
350142 次浏览

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

eval(settings.functionName + '(' + t.parentNode.id + ')');
eval("javascript code");

它在处理JSON时被广泛使用。

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

settings.functionName(t.parentNode.id);

否则,如果settings.functionName只是函数名,也可以这样做:

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

不需要eval()

鉴于我讨厌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);
}

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的方法调用。)

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

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

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

再次强调,如果有其他方法,不要使用eval或这个方法。

这花了我一段时间来弄清楚,因为传统的window['someFunctionName']()起初并不适合我。我的函数名是作为AJAX响应从数据库中提取的。此外,由于某种原因,我的函数是在窗口的作用域之外声明的,所以为了解决这个问题,我不得不重写我调用的函数

function someFunctionName() {}

window.someFunctionName = function() {}

从那里,我可以轻松地调用window['someFunctionName']()。我希望这能帮助到一些人!

我更喜欢使用这样的方法:

window.callbackClass['newFunctionName'] = function(data) { console.log(data) };
...
window.callbackClass['newFunctionName'](data);

在使用CommonJS规范的javascript中,比如node.js,你可以做我下面展示的事情。这对于通过字符串访问变量非常方便,即使它没有在window对象上定义。如果有一个名为MyClass的类,定义在一个名为MyClass.js的CommonJS模块中

// MyClass.js
var MyClass = function() {
// I do stuff in here. Probably return an object
return {
foo: "bar"
}
}


module.exports = MyClass;

然后你可以在另一个名为MyOtherFile.js的文件中做这个漂亮的巫术

// MyOtherFile.js


var myString = "MyClass";


var MyClass = require('./' + myString);
var obj = new MyClass();


console.log(obj.foo); // returns "bar"

CommonJS如此令人愉快的另一个原因。

下面是一个更通用的方法来做同样的事情,同时支持作用域:

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

希望它能帮助一些人。

根据Nicolas Gauthier的回答:

var strng = 'someobj.someCallback';
var data = 'someData';


var func = window;
var funcSplit = strng.split('.');
for(i = 0;i < funcSplit.length;i++){
//We maybe can check typeof and break the bucle if typeof != function
func = func[funcSplit[i]];
}
func(data);

我希望能够将函数名作为字符串,调用它,并将参数传递给函数。我无法得到这个问题的选定答案来做到这一点,但这个回答准确地解释了它,这里是一个简短的演示。

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


functionName = 'test_function';


window[functionName]('works!');

这也适用于多个参数。