我们有产品(普通桌面应用程序)想要从 Adobe 产品(从在这些产品中打开的文档)中提取一些数据。由于 Apple 事件太慢,我们实现了一个自定义互操作,通过套接字将生成的 jsx(Adobe 的 ActionScript3,基于不久前的 JavaScript 1.5)发送到 Adobe 产品进程。这比使用事件快 2000 多倍,但迫使我们做一些涉及 的技巧eval
,当前的目标是最大限度地减少非隔离的 无意中破坏 JSX 引擎状态的风险eval
。
该代码运行在受信任的环境(而不是浏览器)中,并且代码本身也是受信任的,因此任何有关安全的考虑eval
都不适用。该问题的主要目标是防止eval
.
当使用 时eval
,最后一个表达式的结果被视为整个 的返回值eval
,例如以下代码的 -ing 结果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
?
只需从函数返回评估代码:
或者正如迈克建议的那样:
eval
请注意,为了技术正确性,您显示的初始块不仅仅会导致 12,还会导致您编写的所有内容=)eval
是一个暂停 JS 执行的宏,在您提供的代码中进行 subs,执行它,然后恢复常规执行。因此,在这种情况下,结果是两个新变量x
,并且y
在运行的同一范围eval
内,“12”只是来自赋值正在返回操作这一事实。如果您不想在您的范围中引入任何新内容,请记住这
eval
是一个宏:将其放在您需要的代码中:(或者使用亚历山大的解决方案,您可以创建一个“真正的”函数,并将
eval
其作为函数体)当然,这也可以接受争论:
现在将运行一个IIFE,它会执行它需要执行的任何操作,返回 12,然后进行垃圾收集。
当然,这是重要的部分:如果这就是您所需要的,那么您不需要评估任何东西。您只需编写该函数并使用已有的值调用它即可。即使在 Adobe 脚本中,您几乎从未真正需要过
eval
。