我正在编写一些JavaScript代码来解析用户输入的函数(用于类似电子表格的功能)。解析完公式后,我可以将其转换为JavaScript并在其上运行eval()以产生结果。
然而,我总是避免使用eval(),因为它是邪恶的(而且,无论正确与否,我一直认为它在JavaScript中更邪恶,因为要计算的代码可能会被用户更改)。
那么,什么时候可以使用它呢?
我正在编写一些JavaScript代码来解析用户输入的函数(用于类似电子表格的功能)。解析完公式后,我可以将其转换为JavaScript并在其上运行eval()以产生结果。
然而,我总是避免使用eval(),因为它是邪恶的(而且,无论正确与否,我一直认为它在JavaScript中更邪恶,因为要计算的代码可能会被用户更改)。
那么,什么时候可以使用它呢?
当前回答
Eval()并不坏。或者,如果是的话,它是邪恶的,就像反射、文件/网络I/O、线程和IPC在其他语言中的“邪恶”一样。
如果,出于您的目的,eval()比手动解释更快,或者使您的代码更简单,或更清楚……那么你应该使用它。如果两者都不是,那么你就不应该这么做。就这么简单。
其他回答
在Chrome (v28.0.1500.72)中调试时,我发现如果变量没有在产生闭包的嵌套函数中使用,则它们不会绑定到闭包。我想,这是JavaScript引擎的优化。
但是:当eval()在导致闭包的函数中使用时,外部函数的所有变量都被绑定到闭包中,即使它们根本没有被使用。如果有人有时间测试内存泄漏是否会由此产生,请在下面给我留言。
下面是我的测试代码:
(function () {
var eval = function (arg) {
};
function evalTest() {
var used = "used";
var unused = "not used";
(function () {
used.toString(); // Variable "unused" is visible in debugger
eval("1");
})();
}
evalTest();
})();
(function () {
var eval = function (arg) {
};
function evalTest() {
var used = "used";
var unused = "not used";
(function () {
used.toString(); // Variable "unused" is NOT visible in debugger
var noval = eval;
noval("1");
})();
}
evalTest();
})();
(function () {
var noval = function (arg) {
};
function evalTest() {
var used = "used";
var unused = "not used";
(function () {
used.toString(); // Variable "unused" is NOT visible in debugger
noval("1");
})();
}
evalTest();
})();
我想在这里指出的是,eval()不一定指向本机eval()函数。这完全取决于函数的名称。因此,当使用别名调用本机eval()时(说var noval = eval;然后在内部函数noval(expression);)中,当表达式引用了应该是闭包的一部分但实际上不是的变量时,表达式的求值可能会失败。
由于还没有人提到它,让我补充一下eval对于Webassembly-Javascript互操作非常有用。虽然在您的页面中包含WASM代码可以直接调用的预先制作的脚本当然是理想的,但有时这是不可行的,您需要从Webassembly语言(如c#)传入动态Javascript来真正完成您需要做的事情。
在这种情况下,它也是安全的,因为您可以完全控制传入的内容。好吧,我应该说,这并不比使用c#编写SQL语句更安全,也就是说,无论何时使用用户提供的数据来生成脚本,都需要谨慎地执行(正确转义字符串等)。但在这种情况下,它在互操作场景中有一个明确的位置,远非“邪恶”。
只要可以确定代码的源代码来自您或实际用户,就没有理由不使用eval()。尽管他可以操纵发送到eval()函数的内容,但这并不是一个安全问题,因为他能够操纵网站的源代码,因此可以改变JavaScript代码本身。
所以…何时不使用eval()?Eval()只应该在第三方有可能更改它的情况下才使用。比如拦截客户端和服务器之间的连接(但如果这是一个问题,请使用HTTPS)。你不应该用eval()来解析别人写的代码,比如在论坛上。
如果可能的话,只在测试期间使用。还要注意eval()比其他专门的JSON等求值器要慢得多。
如果你可以完全控制传递给eval函数的代码,那么使用它是可以的。