为什么Javascript Eval比较慢,什么时候不应该

时间:2014-06-22 18:29:48

标签: javascript google-chrome eval

所以我正在尝试创建我自己的JS框架,仅仅是为了我自己的乐趣(并且可能转换为有用的)并且我大部分时间都专注于动态生成JS(因为JS具有更高级别的语言 - 在 - 中间是坏主意,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

1 个答案:

答案 0 :(得分:4)

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

这就是为什么通常,当你需要做一个eval时,你可以在另一个函数中执行:这样,编译器可以确保你没有修改eval中的局部范围,并优化了好多了。

JS VMs真的很多关于启发式方法。他们试图猜测你想做什么,并针对一般情况进行优化。 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