study
study copied to clipboard
eval
eval() 是魔鬼
特性
将字符串变为可执行代码执行,同样能做到的这点的还有 Function
setTimeout
setInterval
。
缺陷
-
开发者工具无法进行断点调试
-
性能问题
现代浏览器有两种编译模式:fast path 和 slow path,fast path 用来编译稳定和可预测代码(stable and predictable),slow path 用来便于不可预测代码。 eval 的执行的字符串代码属于不可预测代码,使用 slow path 模式。
-
安全问题
容易引起 XSS 攻击,对信息源要有充分的保证和信任。
-
作用域问题
eval 的字符串代码能访问到外部作用域,并且它也能对外部作用域中的变量进行修改。与此相对,Function 的字符串代码只能访问到全局作用域并且修改。
// 使用 eval var a = 1; console.log(a); // => 1 (function () { var a = 2; console.log(a); // => 2 eval('a = 3; console.log(a);'); // => 3 console.log(a); // => 3 })(); console.log(a); // => 1
// 使用 Function var a = 1; console.log(a); // => 1 (function () { var a = 2; console.log(a); // => 2 Function('a = 3; console.log(a);')(); // => 3 console.log(a); // => 2 })(); console.log(a); // => 3
总结
虽然 eval 有诸多缺陷,但也并不是没有用武之地,比如 webpack 开发环境构建提供 eval 模式加速构建,每个模块使用 eval() 执行。富文本编辑器也会有使用需求。
对于某些需要执行字符串代码的需求,依据实际需求情况分析使用 Function 还是 eval。核心在于开发人员素质,要有能力完全驾驭这两个函数,魔鬼 😈 也是可以好好利用的。