前言
估计稍微接触过前端的人都知道eval不推荐使用,但是有没有想过到底是哪些原因不推荐使用呢?
缺点分析
- 可读性差;
- 性能差;
- 不易维护、不易调试、不易优化;
- 安全问题,它会执行任意传给它的代码,在代码字符串未知或者是来自一个不信任的源时,绝对不要使用 eval,比如说稍不注意容易引起XSS攻击;
- 作用域问题;
当然性能差是相对的,现代浏览器中其实eval的性能很多时候还是比较好的,比如eval一个JSON串肯定比自己去写一个JSON解析工具快。
还有一个容易被漏掉的缺点是作用域问题。
作用域问题
eval的作用:
eval
函数的作用是在当前作用域中执行一段JavaScript
代码字符串,但是只在被直接调用并且调用函数就是eval
本身时才在当前作用域执行。
如何理解上面的“只在被直接调用并且调用函数就是eval本身”呢,先来看个例子:
var a = 1;
function test()
{
var a = 2;
eval('a = 3');
console.log(a); // 3
}
test();
console.log(a); // 1
上面的代码应该没啥问题,但是如果改成下面这样呢:
var a = 1;
function test()
{
var a = 2;
var temp = eval;
temp('a = 3');
console.log(a); // 2
}
test();
console.log(a); // 3
上面的代码等价于在全局作用域中调用 eval,上面的代码等价于:
var a = 1;
function test()
{
var a = 2;
eval.call(window, 'a = 3');
console.log(a); // 2
}
test();
console.log(a); // 3
另外,我们知道setTimeout
和setInterval
都可以接受字符串作为它们的第一个参数,注意这个字符串总是在全局作用域中执行,也就是说 eval 在这种情况下没有被直接调用。
结论
任何情况下我们都应该避免使用 eval 函数,任何使用它的代码都会在它的工作方式、性能和安全性方面受到质疑。 如果一些情况必须使用到 eval 才能正常工作,首先它的设计会受到质疑,这不应该是首选的解决方案, 一个更好的不使用 eval 的解决方案应该得到充分考虑并优先采用。