【问题标题】:Why Javascript Eval is slower, when it shouldn't be为什么 Javascript Eval 更慢,而不应该是
【发布时间】:2014-06-22 18:29:47
【问题描述】:

所以我尝试创建自己的 JS 框架只是为了我自己的乐趣(然后可能会转化为有用性),我大部分时间都专注于动态生成 JS(因为 JS 作为语言的水平更高) the-middle 是个坏主意,IMO)

我遇到了一个麻烦。我试图做以下事情

var f = null;
var converted = "f = function(){ <do something here>";
for(var x in list)
 converted+=list[x];
converted+="};";
eval(converted);

所以这几乎将构造函数写入 f,我可以稍后执行。

但这里有个问题——它运行得比我完全在文件中编写 f 的代码要慢,这很奇怪。让我解释一下为什么这对我来说很奇怪:当您每次只运行 eval 时,Chrome 预编译器(或任何浏览器预编译器 - chrome 是我的目标)无法缓存编译代码,因为它期望它会随着每个跑。

但是,当您将其保存到函数时,它会创建一个新的 VM 机器文件,因为保存函数的代码后,您无法更改它。那么,为什么当我进行这样的评估时,它的运行速度比正常执行慢?我的意思是在代码多次执行之后。为什么这很重要?

PS:我上面展示的方法每次都比评估更快。所以我不明白为什么秒表会在中间显示时间,再次忽略前 1-10 个调用

PPS:测试用例:http://jsperf.com/evaluated-function-vs-real-function/2

【问题讨论】:

  • when you save this to a function - 你如何将它保存到函数中?从您发布的代码中,我没有看到评估代码被转换为函数。
  • 相信我,确实如此。当您评估变量“已转换”时,执行 f=function()...,它将新函数写入变量 f
  • 当我测试它时,我发现常规函数和使用eval创建的函数之间没有性能差异:jsperf.com/evaluated-function-vs-real-function
  • 啊,没关系 - 我没有看到 f 在您评估的代码之外的任何地方引用。
  • 这里使用 Function 构造函数可能会有所帮助。说真的,以这种方式使用 eval 是非常危险的,并且被认为是有害的。至少您应该将函数值分配为 eval 调用的结果,即 var converted = "var f = function() { ..."; ... converted += "}; f;" var f = eval(converted); 但我建议 var f = new Function(converted); 其中 converted 只是您的函数的主体。

标签: javascript google-chrome eval


【解决方案1】:

eval 基本上是不可优化的,因为编译器不知道它在做什么。即使你将它保存到一个函数中,编译器也必须选择退出很多优化,因为以某种方式更改你的代码可能会破坏 eval 函数。

这就是为什么,通常,当您需要进行 eval 时,您会在另一个函数中进行:这样,编译器可以确定您没有修改 eval 中的本地范围,并且优化得更好.

JS 虚拟机确实有很多启发式方法。他们试图猜测您想要做什么,并针对一般情况进行优化。 eval(或new Function)阻止他们这样做。

Function.new可能会快一点,因为编译器会知道它不会尝试修改作用域。


还有!请注意,eval 的行为可能与您习惯的有所不同。例如,eval('a')(0, eval)('a') 不相同

我会用这个来演示一下

window.a = 5;
void function () {
  var a = 1;
  eval('a = 2');
  console.log(a);
  console.log(window.a);
}();

这将打印1 然后5

window.a = 5;
void function () {
  var a = 1;
  (0,eval)('a = 2'); // <- this line has changed
  console.log(a);
  console.log(window.a);
}();

然而,这将打印1 然后2

您也可以阅读:Global eval, what are the options

【讨论】:

猜你喜欢
  • 2016-05-23
  • 2013-07-05
  • 2011-04-01
  • 2017-01-01
  • 1970-01-01
  • 2011-05-10
  • 2018-05-10
  • 2015-09-03
  • 2014-03-12
相关资源
最近更新 更多