is eval evil?

最近项目中, 一个为了确保安全性而做的任务是移除代码中的eval. 我对eval的不好略有耳闻, 但是它到底有多不好? 今天了解下.

Douglas Crockford说过:

The eval function (and its relatives, Function, setTimeout, and setInterval) provide access to the JavaScript compiler. This is sometimes necessary, but in most cases it indicates the presence of extremely bad coding. The eval function is the most misused feature of JavaScript.

这句话被很多人用来佐证eval的不好. eval被认为为攻击者进行Cross-Site Scripting (XSS) 攻击创造了便利. 但其实使用得当, eval并没有什么问题.

错误应用

比方说下面这段代码, 利用eval去判断一个表单元素是否被选中.

function isChecked(optionNumber) {
    return eval("forms[0].option" + optionNumber + ".checked");
}

var result = isChecked(1);

这段代码很容易用没有eval的方式实现.

function isChecked(optionNumber) {
    return forms[0]["option" + optionNumber].checked;
}

var result = isChecked(1);

这类似错误的eval应用可以简单地使用[]来避免.

调试

eval中的代码为调试带来了难度. 现在Chrome Dev Tool可以debugeval中的代码, 但是仍然很麻烦. 所以, 从这点出发, 为了开发效率, 也尽量不要用eval.

效率

旧的浏览器中, 如果你使用eval, 浏览器就要进行两次解析. 第一次解析JS代码本身, 第二次解析eval中的代码. 在不带JS编译引擎的浏览器中, 效率可能相差十倍.

即使对于带JS编译引擎的浏览器, eval还是有问题. 大多数引擎运行代码时会在两种模式中选择: 一个是fast path, 一个是slow path. 如果代码稳定, 比较容易预测, 那么引擎会使用fast path运行代码, 效率高很多. 如果代码很难预测, 那只能用slow path运行了. 由于带eval的代码本身很难预测, 所以会走slow path, 因此也会造成效率低下.

安全性

eval最让人头疼的地方就是安全性了. 如果你将用户的输入作为eval的参数, 那么就有XSS的风险. 但是你只要确保不做出这种事, 使用eval也是没什么问题的.

另外一点是, 有些人说, 如果你使用eval去运行浏览器返回的代码, 那么就有可能受到中间人攻击 (man-in-the-middle attack). 但是事实上, 如果一个人真的做到了中间人攻击, 除了用eval, 有更多简单的方法让他运行恶意代码, 比如:

  1. 在代码中插入

你可能感兴趣的:(is eval evil?)