eval函数是一种强大而简单的动态生成代码的方法,那么有什么注意事项呢?


当前回答

这并不总是一个坏主意。以代码生成为例。我最近写了一个叫做Hyperbars的库,它在虚拟世界和把手之间架起了桥梁。它通过解析句柄模板并将其转换为虚拟dom使用的超脚本来实现这一点。超脚本首先作为字符串生成,在返回它之前,eval()将其转换为可执行代码。我发现eval()在这种特殊情况下与邪恶完全相反。

基本上从

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

这个

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

eval()的性能在这种情况下不是问题,因为您只需要解释一次生成的字符串,然后多次重用可执行输出。

如果您好奇的话,您可以看到代码生成是如何实现的。

其他回答

需要记住的一件事是,您可以经常使用eval()在其他受限制的环境中执行代码——阻塞特定JavaScript函数的社交网站有时可以通过在eval块中分解它们来愚弄它们

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

因此,如果你想运行一些JavaScript代码,否则它可能是不允许的(Myspace,我看着你…),那么eval()可能是一个有用的技巧。

然而,由于上面提到的所有原因,你不应该在你自己的代码中使用它,在那里你有完全的控制权——这是没有必要的,最好把它归到“棘手的JavaScript hacks”架子上。

我相信这是因为它可以从字符串执行任何JavaScript函数。使用它可以使人们更容易向应用程序中注入恶意代码。

这并不总是一个坏主意。以代码生成为例。我最近写了一个叫做Hyperbars的库,它在虚拟世界和把手之间架起了桥梁。它通过解析句柄模板并将其转换为虚拟dom使用的超脚本来实现这一点。超脚本首先作为字符串生成,在返回它之前,eval()将其转换为可执行代码。我发现eval()在这种特殊情况下与邪恶完全相反。

基本上从

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

这个

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

eval()的性能在这种情况下不是问题,因为您只需要解释一次生成的字符串,然后多次重用可执行输出。

如果您好奇的话,您可以看到代码生成是如何实现的。

如果你想让用户输入一些逻辑函数并计算与或,那么JavaScript的eval函数是完美的。我可以接受两个字符串和eval(ate) string1 === string2等。

Eval并不总是邪恶的。有些时候,这是非常合适的。

然而,eval在当前和历史上都被那些不知道自己在做什么的人过度使用。不幸的是,这包括编写JavaScript教程的人,在某些情况下,这确实会产生安全后果——或者,更常见的是,简单的错误。所以,我们在eval上加的问号越多越好。任何时候你使用eval你都需要检查你正在做的事情,因为你可能会用一种更好,更安全,更干净的方式来做。

举一个非常典型的例子,设置id存储在变量'potato'中的元素的颜色:

eval('document.' + potato + '.style.color = "red"');

如果上面这类代码的作者对JavaScript对象工作的基本原理有所了解,他们就会意识到可以使用方括号来代替字面上的点名称,从而消除了eval的需要:

document[potato].style.color = 'red';

...这更容易阅读,也更少潜在的错误。

(但是,那些/真正/知道自己在做什么的人会说:

document.getElementById(potato).style.color = 'red';

这比直接从文档对象中访问DOM元素更可靠。)