3 ms·
Depends on your definition of "much", but more than you might expect. Pre-parsing is an obvious big win, but there's also classical compiler optimizations: con
by ridiculous_fish 8y ago
Depends on your definition of "much", but more than you might expect.
Pre-parsing is an obvious big win, but there's also classical compiler optimizations: constant propagation, DCE, certain inlining, etc. Local variables can be statically determined to be non-captured, which means they can be stack allocated.
One totally bizarre but profoundly useful property of JS is the restrictions on eval. eval has the ability to run new code, but this code is globally scoped unless it's run as the "eval" function itself. [1] Thus it's easy to decide which local variables are immune to eval; this in turn unlocks lots of optimizations. To my knowledge this weirdo behavior is not present in Python or other dynamic languages.
1: https://es5.github.io/#x15.1.2.1.1 https://es5.github.io/#x15.1.2.1.1
- maxxxxx 8y agoI guess that makes sense. You can optimize the not so dynamic parts of the code.
- jacobush 8y agoI can not visualize what you mean. What does it mean to be run as the eval function itself?
- ridiculous_fish 8y agoIt's the dorkiest thing you can imagine, literally a string comparison against "eval". In JS functions are first class, so one might attempt: function wut() { var x = 1; var obj = {sneaky: eval}; obj.sneaky("x++"); console.log(x); } Here we are calling `obj.sneaky()` with some JS code. The sneaky property is the eval function: won't it run the code and thereby increment x? The answer is no: because the caller's name 'obj.sneaky' does not literally compare equal to "eval", the eval function is run with global scope instead of local scope. Therefore the 'x' inside the eval'd string is a global property, not the local variable. So with this analysis we can (statically) apply constant propagation and replace x with 1. Now if we replace obj.sneaky with eval, the string comparison succeeds, it becomes "direct eval", and the constant propagation is invalid.
- tobyhinloopen 8y agoTIL. I love this.
- sabas123 8y agoSince this seems such a roundabout way of calling eval, does anyone actually use this?
- ridiculous_fish 8y agoWell usually we want to run code at global scope, and direct eval is an obstacle. There's workarounds like "(1, eval)", but the most idiomatic way is the Function constructor, which always runs code at global scope. That leads to this pattern: var global = (new Function("return this")()) which really is the safest way to get the global object. I know right.