Recently I’ve read this performance guide Let’s make the web faster and was puzzled by “Avoiding pitfalls with closures” recommendations (as if these advices were given for CommonLisp users where variable scoping is dynamic):
var a = 'a'; function createFunctionWithClosure() { var b = 'b'; return function () { var c = 'c'; a; b; c; }; } var f = createFunctionWithClosure(); f();when
fis invoked, referencingais slower than referencingb, which is slower than referencingc.
It’s quite evident that referencing local variable c is faster than b, but if the iterpreter is written properly (without dynamic scoping – something like chained hashtable lookup..) the speed difference should be only marginal. Or not?
You’re right. Modern JS engines will optimize the
scope chain lookupand theprototype chain lookuplike a lot. Means, AFAIK the engine trys to hold some sort of hash-table with access nodes underneath.This only works if there is no
eval()(explicity or implicitly, e.g.setTimeout) or atry-catchclause ora with statementinvoked. Because of such constructs, the interpretator can’t be sure about how to access data and it needs to “fallback” into a classicalscope chain lookupwhich really means, it has to crawl through all parent contextvariable / activation objectsand try to resolve the searched variable name.This process of, of course, will take more time for objects/names which are located “far away” from where the lookup processed was started. That in turn means, that accessing data on the
global objectwill always be the slowest.In your snippet, the lookup process for
awould go likeThe described lookup procedure is for ECMAscript Edition 262 3rd edition. ECMAscript edition 5 has some fundamental changes there.