使用JavaScript eval()创建的匿名函数的执行

20

我有一个函数,它的内容是以字符串形式存在的。

var funcStr = "function() { alert('hello'); }";

现在,我使用eval()将该函数实际获取到一个变量中。

var func = eval(funcStr);

如果我没记错,在Chrome和Opera中,只需调用

func();

在某个浏览器中,我调用了那个函数并且弹出了警告框。但是在其他浏览器中却没有反应。

我不希望争论哪种方法是正确的,而是想知道如何做到这一点?我希望能够调用 variable(); 来执行存储在该变量中的函数。


我想知道为什么你需要将匿名函数表示为字符串字面量,而不是使用命名函数? - Russ Cam
FYI:我正在为我的Web应用程序定义自己的脚本。我正在编写一个解释器,需要动态构建JS函数,然后将它们创建为实际可执行函数。 - anonymous
为什么你不用传统的方式编写解释器呢? - Breton
1
我不知道如何用“传统方式”写它。我发现这种方法更简单。如果你能给我指点一下如何“传统地”完成它,那就太好了。 - anonymous
3
在将字符串传递到 eval 之前,尝试将函数用括号括起来。var funcStr = "( function() { alert('hello'); } )"; - awhie29urh2
@人们为什么问为什么?——因为我想了解语言的限制,探索其边界,这样我就能深入了解它,而不是提出这些问题,我知道如何回答它们。 - Mike
11个回答

34

这个怎么样?

var func = new Function('alert("hello");');

为函数添加参数:

var func = new Function('what', 'alert("hello " + what);');
func('world'); // hello world

请注意,函数是对象,可以像其他对象一样分配给任何变量:

var func = function () { alert('hello'); };
var otherFunc = func;
func = 'funky!';

function executeSomething(something) {
    something();
}
executeSomething(otherFunc); // Alerts 'hello'

1
这是一种既优雅又适用于所有浏览器的方法。谢谢 :) - anonymous

15

IE因为安全原因无法 eval 函数。

最佳解决方法是将函数放在数组中,像这样:

var func = eval('[' + funcStr + ']')[0];

可以的。但是,函数字面量不是语句,所以它们需要在周围加上括号,这比你的数组解决方案更清晰。 - Ruan Mendes
3
@Juan:错了,它做不到。尝试使用javascript:alert(eval('( function() { return 3; } )')); - SLaks
我的错,我建议使用括号而不是你的数组解决方案,我没有意识到在IE中无法工作。 - Ruan Mendes

8
我知道这篇文章有点老了,但它是我在Google搜索中得到的唯一有效结果,可以用于评估匿名JavaScript函数字符串。
最终我从jQuery谷歌小组的帖子中找到了解决方法。
eval("false||"+data)

其中,data是你的函数字符串,如"function() { return 123; }"

到目前为止,我只在IE8和FF8(我的个人电脑上的浏览器)中尝试过这个方法,但我相信jQuery在内部使用它,因此它几乎可以在任何地方使用。


我不明白为什么其他人似乎没有这个问题。这真的太棒了,谢谢! - Shwouchk
我们也可以这样做:eval('!1||'+funcBody); - Bharata

6
尝试一下。
var funcStr = "var func = function() { alert('hello'); }";

eval(funcStr);

func();

嘿,谢谢,那个方法可行!但是用那种方式看起来有点奇怪 :D。 - anonymous

4

像这样使用 eval:

var func = eval('(' + funcStr + ')');

这是我最初的想法,但我相当确定它仅适用于对象。 - karim79
无论是正确的方式还是错误的方式,它在IE中都不起作用。 - anonymous
1
尝试在IE上运行此代码失败:eval ('(function(){return 'Yay'})')()。然而,eval ('[function(){return 'Yay'}][0]')()可以正常工作。 - Ruan Mendes

4
我们通过准备通用的函数解析器来解决这个问题,该解析器将字符串转换为真正的JavaScript函数:
if (typeof String.prototype.parseFunction != 'function') {
    String.prototype.parseFunction = function () {
        var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
        var match = funcReg.exec(this.replace(/\n/g, ' '));

        if(match) {
            return new Function(match[1].split(','), match[2]);
        }

        return null;
    };
}

使用示例:

var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));

func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();

这里是jsfiddle,点击链接这里

1
你真是个天才!通过一些修改来去除注释,你的函数救了我的一天,非常感谢你。 - Aaron Meese
1
谢谢!我很高兴它有帮助。 - Mr. Pumpkin

1

这也可以。

var func = eval("_="+funcStr);

0

无需使用eval()的EVAL...

function evalEx(code){
  var result,D=document,S=D.createElement('script'),
  H=D.head||D.getElementsByTagName['head'][0],
  param=Array.prototype.slice.call(arguments);
  code='function evalWE(){'+code+'}';
  S.innerText===''?S.innerText=code:S.textContent=code;
  H.appendChild(S);
  result=evalWE.apply(this,param);
  H.removeChild(S);
  return result
}

使用示例:

ABC=evalEx('return "ABC"');
nine=evalEx('return arguments[1]+arguments[2]',4,5);

哈哈,你刚刚给了我一个理由,为什么Google打包应用程序不允许在HTML中使用内联JavaScript:http://developer.chrome.com/extensions/contentSecurityPolicy.html - nraynaud

0
一个简单的例子,将函数定义为字符串,使用eval()执行它,并在立即调用函数时传入参数(然后将结果输出到控制台): console.log('eval: %s', eval("(function(foo) { return foo.bar; })")({"bar": "12345"})); 这将产生以下输出: eval: 12345

-1

另外也可以运行的是

var myFunc = function(myParam){
   // function body here
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接