eval()
以得出结果。然而,如果可以避免使用
eval()
,我总是回避它,因为它是有害的(而且,正确或错误地说,我一直认为在JavaScript中它甚至更加有害,因为要评估的代码可能会被用户更改)。那么,在什么情况下可以使用它呢?
eval()
以得出结果。eval()
,我总是回避它,因为它是有害的(而且,正确或错误地说,我一直认为在JavaScript中它甚至更加有害,因为要评估的代码可能会被用户更改)。接下来谈谈您的具体情况。根据我所了解的,您自己生成字符串,因此假设您小心翼翼地不允许生成像“rm -rf something-important”这样的字符串,则不存在代码注入风险(但请记住,在一般情况下确保这一点非常非常困难)。而且,如果您在浏览器中运行,则代码注入的风险相对较小,我相信。
就性能而言,您需要权衡其与编码的易用性。在我看来,如果你正在解析这个公式,那么最好在解析过程中计算结果,而不是运行另一个解析器(eval()内部的解析器)。但使用eval()可能更容易编码,而且性能损失可能不会被注意到。在这种情况下,看起来eval()并不比其他可能为您节省时间的任何函数更邪恶。
eval()
的 JavaScript 代码,他们也可以在一开始就更改页面源代码,并控制用户的信息...我看不出有什么区别。 - Walt Weval()
不是恶行。如果它是恶行的话,那么在其他语言中反射、文件/网络 I/O、线程和 IPC 也是“恶行”。
如果在你的情况下 eval()
比手动解析更快,或者使你的代码更简单、更清晰……那么你应该使用它。如果没有,则不应该使用。就这么简单。
当您信任数据源时。
在JSON的情况下,由于它来自您控制的web服务器,因此更难篡改源数据。只要JSON本身不包含用户上传的数据,使用eval函数并没有太大的弊端。
在所有其他情况下,我都会尽力确保用户提供的数据符合我的规则,然后再将其提供给eval()函数。
eval
方法也不能正确解析所有有效的 JSON 字符串。例如,JSON.parse(' "\u2028" ') === "\u2028"
,但是 eval(' "\u2028" ')
会引发异常,因为在 JavaScript 中 U+2028 是一个换行符,但在 JSON 中它不是一个换行符。 - Mike Samuel让我们认真面对:
现在每个主流浏览器都有内置控制台,黑客可以大量使用它来调用任何函数和任何值 - 他们为什么要费劲地使用 eval 语句 - 即使他们能做到呢?
如果编译2000行JavaScript代码需要0.2秒,那么如果我评估四行JSON,我的性能损失是多少?
即使是 Crockford 对 "eval 是邪恶的" 的解释也很弱。
eval 是邪恶的,eval 函数是 JavaScript 中被滥用最多的功能。避免使用它
正如 Crockford 自己可能会说的那样,“这种说法往往会引发非理性的神经质。不要相信它。”
了解 eval 并知道何时可能有用更为重要。例如,eval 是用于评估由您的软件生成的服务器响应的明智工具。
顺便说一下:Prototype.js 直接调用 eval 五次(包括 evalJSON() 和 evalResponse()),jQuery 在 parseJSON 中使用它(通过 Function 构造函数)。
我倾向于遵循 Crockford的建议,尽量避免使用eval()
。即使有看起来需要使用它的方式,也可以用其他方法代替。例如,setTimeout()
允许你传递一个函数而不是 eval。
setTimeout(function() {
alert('hi');
}, 1000);
即使是一个可信任的来源,我也不使用它,因为JSON返回的代码可能会乱码,最好情况下会有一些奇怪的事情发生,最坏的情况是暴露出一些糟糕的东西。
如果您创建或清理了您使用eval
的代码,则它永远不会是恶意的。
如果在服务器上运行时,eval
使用由未经过开发者创建或未经过开发者清理的客户端提交的输入,则eval
是恶意的。
如果在客户端上运行,即使使用由客户端编写的未经过清理的输入,eval
也不是恶意的。
显然,您应该始终对输入进行清理,以控制您的代码使用的内容。
客户端可以运行他们想要的任何任意代码,即使开发人员没有编写它;这不仅适用于被评估的内容,也适用于调用eval
本身。
eval
,他们可以做一些像将B人的cookies发送到A人的远程服务器之类的事情。 - Deanvelopereval
和设置innerHTML
一样容易引起安全漏洞。只要你知道自己在做什么,就没问题,但如果不小心,它可能会打开一些攻击的大门(例如窃取cookie)。 - DeanveloperEval是编译的补充,用于模板代码。所谓模板,就是编写一个简化的模板生成器,生成有用的模板代码,从而提高开发速度。
我编写了一个框架,在这个框架中,开发人员不使用EVAL,但这个框架必须使用EVAL来生成模板。
通过以下方法可以提高EVAL的性能:不要执行脚本,而是返回一个函数。
var a = eval("3 + 5");
var f = eval("(function(a,b) { return a + b; })");
var a = f(3,5);
缓存f肯定会提高速度。
此外,Chrome允许非常容易地调试这些功能。
关于安全性,使用eval或不使用eval几乎没有任何区别,
如果你的服务器端安全性足够坚固,可以从任何地方攻击你,那么你不必担心EVAL。正如我所提到的,如果EVAL不存在,攻击者有很多工具可以入侵你的服务器,而不管你的浏览器是否具有EVAL功能。
EVAL仅适用于生成一些模板,以根据预先未使用的内容进行复杂的字符串处理。例如,我更喜欢
"FirstName + ' ' + LastName"
相对于
"LastName + ' ' + FirstName"
function (first, last) { return last + ' ' + first }
。 - Konrad Borowskieval
的威胁主要来自于其他用户。假设您有一个设置页面,可以让您设置如何向他人显示您的名称。也假设当您编写该页面时没有考虑得很清楚,因此您的选择框中有像<option value="LastName + ' ' + FirstName">Last First</option>
这样的选项。我打开我的开发工具,更改一个选项的“值”为alert('PWNED!')
,选择更改后的选项并提交表单。 现在,任何时候其他人可以看到我的显示名称,这段代码都会运行。 - cHao(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,因为它是危险的,但是我看到同样的人动态地使用Function和setTimeout,所以他们在幕后使用eval :D
顺便说一下,如果你的沙箱不够安全(例如,如果你正在处理允许代码注入的网站),那么eval就是你最后的问题。安全的基本规则是,所有输入都是危险的,但在JavaScript的情况下,甚至JavaScript本身也可能是危险的,因为在JavaScript中,你可以覆盖任何函数,你就不能确定你是否在使用真正的函数,所以,如果一个恶意代码在你之前启动,你就不能信任任何JavaScript内置函数:D
现在这篇文章的结尾是:
如果你真的需要它(80%的情况下eval是不需要的),并且你确信自己在做什么,那么就使用eval(或者更好的Function ;)),闭包和面向对象编程可以覆盖80/90%的情况,其中eval可以用其他类型的逻辑进行替换,其余的是动态生成的代码(例如,如果你正在编写解释器),正如你已经说过的评估JSON(在这里,你可以使用Crockford安全评估 ;))
唯一需要使用eval()的情况是当您需要动态运行JS时。我说的是从服务器异步下载的JS...
...而且有9次中的9次,通过重构代码很容易避免这种情况。