我正在编写一些JavaScript代码来解析用户输入的函数(用于类似电子表格的功能)。解析完公式后,我可以将其转换为JavaScript并在其上运行eval()以产生结果。
然而,我总是避免使用eval(),因为它是邪恶的(而且,无论正确与否,我一直认为它在JavaScript中更邪恶,因为要计算的代码可能会被用户更改)。
那么,什么时候可以使用它呢?
我正在编写一些JavaScript代码来解析用户输入的函数(用于类似电子表格的功能)。解析完公式后,我可以将其转换为JavaScript并在其上运行eval()以产生结果。
然而,我总是避免使用eval(),因为它是邪恶的(而且,无论正确与否,我一直认为它在JavaScript中更邪恶,因为要计算的代码可能会被用户更改)。
那么,什么时候可以使用它呢?
当前回答
当你相信消息来源时。
在JSON的情况下,它或多或少很难篡改源代码,因为它来自你控制的web服务器。只要JSON本身不包含用户上传的数据,使用eval就没有什么大的缺点。
在所有其他情况下,在将用户提供的数据提供给eval()之前,我将竭尽全力确保它符合我的规则。
其他回答
Eval是编译的补充,编译用于代码模板。我所说的模板是指编写一个简化的模板生成器,生成有用的模板代码,从而提高开发速度。
我写了一个框架,其中开发人员不使用EVAL,但他们使用我们的框架,反过来,该框架必须使用EVAL来生成模板。
通过以下方法可以提高EVAL的性能:您必须返回一个函数,而不是执行脚本。
var a = eval("3 + 5");
它应该被组织成
var f = eval("(function(a,b) { return a + b; })");
var a = f(3,5);
缓存肯定会提高速度。
Chrome也允许调试这样的功能非常容易。
在安全性方面,是否使用eval几乎没有什么区别。
First of all, the browser invokes the entire script in a sandbox. Any code that is evil in EVAL, is evil in the browser itself. The attacker or anyone can easily inject a script node in DOM and do anything if he/she can eval anything. Not using EVAL will not make any difference. It is mostly poor server-side security that is harmful. Poor cookies validation or poor ACL implementation on the server causes most attacks. A recent Java vulnerability, etc. was there in Java's native code. JavaScript was and is designed to run in a sandbox, whereas applets were designed to run outside a sandbox with certificates, etc. that lead to vulnerabilities and many other things. Writing code for imitating a browser is not difficult. All you have to do is make a HTTP request to the server with your favourite user agent string. All testing tools mock browsers anyway; if an attacker want to harm you, EVAL is their last resort. They have many other ways to deal with your server-side security. The browser DOM does not have access to files and not a user name. In fact nothing on the machine that eval can give access to.
如果您的服务器端安全性足够坚固,任何人都可以从任何地方进行攻击,那么您就不应该担心EVAL。正如我提到的,如果EVAL不存在,攻击者就有很多工具来入侵你的服务器,而不管你浏览器的EVAL能力如何。
Eval只适用于生成一些模板,根据事先没有使用的内容进行复杂的字符串处理。例如,我更喜欢
"FirstName + ' ' + LastName"
而不是
"LastName + ' ' + FirstName"
作为我的显示名,它可以来自数据库,并且不是硬编码的。
我的使用eval: import的例子。
通常的做法。
var components = require('components');
var Button = components.Button;
var ComboBox = components.ComboBox;
var CheckBox = components.CheckBox;
...
// That quickly gets very boring
但是在eval和一个小helper函数的帮助下,它得到了更好的外观:
var components = require('components');
eval(importable('components', 'Button', 'ComboBox', 'CheckBox', ...));
Importable可能看起来像这样(此版本不支持导入具体成员)。
function importable(path) {
var name;
var pkg = eval(path);
var result = '\n';
for (name in pkg) {
result += 'if (name !== undefined) throw "import error: name already exists";\n'.replace(/name/g, name);
}
for (name in pkg) {
result += 'var name = path.name;\n'.replace(/name/g, name).replace('path', path);
}
return result;
}
让我们看看真正的人:
现在每个主流浏览器都有一个内置的控制台,你想成为黑客的人可以使用它来调用任何值的任何函数-为什么他们会麻烦使用eval语句-即使他们可以? 如果编译2000行JavaScript需要0.2秒,那么如果我计算4行JSON,性能会下降多少?
即使克罗克福德对“eval是邪恶的”的解释也很软弱。
eval是邪恶的,eval函数是最被滥用的功能 JavaScript。避免它
正如克罗克福德自己可能会说的那样:“这种说法往往会产生非理性的神经症。别买它。”
理解eval并知道它什么时候可能有用更重要。例如,eval是评估软件生成的服务器响应的明智工具。
顺便说一句:Prototype.js直接调用eval 5次(包括在evalJSON()和evalResponse()中)。jQuery在parseJSON中使用它(通过函数构造函数)。
当你相信消息来源时。
在JSON的情况下,它或多或少很难篡改源代码,因为它来自你控制的web服务器。只要JSON本身不包含用户上传的数据,使用eval就没有什么大的缺点。
在所有其他情况下,在将用户提供的数据提供给eval()之前,我将竭尽全力确保它符合我的规则。
我倾向于遵循Crockford关于eval()的建议,并完全避免使用它。即使是看起来需要它的方法也不需要。例如,setTimeout()允许您传递一个函数而不是eval。
setTimeout(function() {
alert('hi');
}, 1000);
即使它是一个可信的源,我也不会使用它,因为JSON返回的代码可能是乱码,最好的情况下可能会产生一些不稳定的东西,最坏的情况下可能会暴露一些不好的东西。