初识eval()
eval()函数在很多语言中都有,这仅仅讨论在JavaScript中的情况。由于eval()函数可以将任意字符串当做一个JavaScript代码来执行,所以可谓是特别强大了,经常的使用情况就是,函数名变化,来调用函数之类的。
但是为什么说是魔鬼:
如果你用
eval()
运行的字符串代码被恶意方(不怀好意的人)操控修改,您最终可能会在您的网页/扩展程序的权限下,在用户计算机上运行恶意代码。更重要的是,第三方代码可以看到某一个eval()被调用时的作用域,这也有可能导致一些不同方式的攻击。——MDN
除上面破坏性之外的魔鬼之处:
- 篡改全局变量
- 影响到作用域链
- 要调用JS解释器,通常比替代方案慢
替代方案new Function()
优点:
在new Function()中运行的代码不会自动成为全局变量,eval()是会的,但是为了避免,可以将eval调用封装到一个立即执行的函数中。
var jsstring = 'var un = 1; console.log(un);';
eval(jsstring); // '1'
jsstring = 'var deux = 2; console.log(deux);';
new Function(jsstring)(); // '2'
jsstring = 'var trois = 3; console.log(trois);';
(function () {
eval(jsstring);
})(); // '3'
console.log(typeof un); // 'number'
console.log(typeof deux); // 'undefined'
console.log(typeof trois); // 'undefined'
从上面代码可以看到,eval会影响到全局变量,当然,封装在匿名函数中调用就不会了,而new Function()不会。
eval是可以访问和修改它外部作用域的变量,然而new Function不会。
注意事项:
无论在哪里执行Function,他都仅仅能看到全局作用域,所以下面的变量访问不到。
(function () {
var local = 1;
Function ('console.log(typeof local);')(); // 'undefined'
})();
但是如果间接使用eval(),比如通过一个引用来调用它, 从 ECMAScript 5 起,那么将工作在全局作用域下,而不是局部作用域中。(外部是不能访问内部的,所以下面报错)
function test() {
var a = 1, geval = eval;
eval('console.log(a)'); // 1
geval('console.log(a)'); // ReferenceError: a is not defined
}
对于具体的eval各种使用场景的替代方法,查看下面的链接即可。比如对象的调用使用方括号形式等等。
参考资料
《javasript设计模式》