免责声明:假设问题中提到的代码运行在受信任的环境(而不是浏览器)中,并且代码本身是受信任的。因此,任何有关
eval
的安全考虑都不适用。该问题的主要目标是防止eval
造成的全球范围的污染。
当使用
eval
时,最后一个表达式的结果被视为整个eval
的返回值,例如以下代码的 eval
运算的结果将是 y+2=12
表达式的值。
var res = eval("
var x = 5;
var y = x*2;
y+2;
"); //res = 12
同时,如果我们将这样的代码包装到
Function
构造函数中,那么结果将是undefined
var res = (new Function("
var x = 5;
var y = x*2;
y+2;
")).call(); //res=undefined
要修复最后一个片段,我们需要向最后一个表达式添加显式返回:
var res = (new Function("
var x = 5;
var y = x*2;
return y+2; // <------- changes here
")).call(); //res=12
因此,
eval
和Function
具有不同的返回语义。
而且我不能只用遗留代码中的
eval
替换 Function()
。我还将被迫更改调用方以在代码中添加 return
,传递给 Function()
。
有没有办法避免添加显式返回,因此可以以透明的方式将
eval
替换为 Function()
(假设我们对访问本地范围不感兴趣)?
或者也许存在另一种技术,它可以提供与
eval
等效的技术,这将最大限度地减少全局范围污染的风险,并提供与原始 eval
相同的返回语义?
注意:系统中使用的JS引擎相当老旧,因此不支持
strict mode
和ES6+功能。
只需从函数返回评估代码:
const code = `alert = 1; 2*2`;
const fn = new Function('', `return eval('${code}')`);
console.log(fn());