So i'm trying to create my own JS framework just for my own pleasure (and probably then convert into usefullness) and I most of the time focus on generating JS dynamicly (since having higher level with JS as language-in-the-middle is bad idea, IMO)
And I got into one trouble. I was trying to do following
var f = null;
var converted = "f = function(){ <do something here>";
for(var x in list)
converted+=list[x];
converted+="};";
eval(converted);
So this pretty much writes constructed function to f, that I can later execute.
But here's the catch - it runs slower, than if I just write code of f completely in file, which is very strange. Let me explain why it's strange to me: when you just run eval each time, Chrome precompiler (or whatever browser precompiler - chrome is what I target) can't cache-compile the code, because it expects, that it will change with each run.
However, when you save this to a function, it creates a new VM machine file, because after you saved the function's code, you can't change it. So why, when I do such eval, it runs slower than normal execution? I mean after code was executed more than once. Why this should matter?
PS: The method I had shown above, works faster that eval-ing each time. So I don't understand why stopwatches show time inbetween, again, ignoring first 1-10 calls
PPS: Test case: http://jsperf.com/evaluated-function-vs-real-function/2
eval
is basically unoptimizable because the compiler doesn't know what it's doing. Even if you save it into a function, the compiler has to opt out a lot of optimizations, because changing your code in a certain way might break the eval function.
This is why, usually, when you need to do an eval, you do it in another function : that way, the compiler can be sure you didn't modify local scope in the eval
, and optimizes a lot better.
JS VMs are really a lot about heuristics. They try to guess what you want to do, and optimize for the general case. eval
(or new Function
) prevent them to do a lot of that.
Function.new
might be a little faster, because the compiler will know it won't try to modify the scope.
ALSO ! Note that eval
might act a little differently than what you're used to. For example, eval('a')
and (0, eval)('a')
are not the same :
I'll demonstrate it with this
window.a = 5;
void function () {
var a = 1;
eval('a = 2');
console.log(a);
console.log(window.a);
}();
This will print 1
then 5
window.a = 5;
void function () {
var a = 1;
(0,eval)('a = 2'); // <- this line has changed
console.log(a);
console.log(window.a);
}();
Whereas, this will print 1
then 2
.
You can also read this : Global eval, what are the options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With