Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: why the access to closure variable might be slow

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 f is invoked, referencing a is slower than referencing b, which is slower than referencing c.

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?

like image 598
dennisL Avatar asked Feb 12 '12 12:02

dennisL


1 Answers

You're right. Modern JS engines will optimize the scope chain lookup and the prototype chain lookup like 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 a try-catch clause or a with statement invoked. Because of such constructs, the interpretator can't be sure about how to access data and it needs to "fallback" into a classical scope chain lookup which really means, it has to crawl through all parent context variable / activation objects and 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 object will always be the slowest.

In your snippet, the lookup process for a would go like

anonymous function -> Execution Context -> Activation Object (not found)
anonymous function -> Execution Context -> [[ Scope ]] 
    - createFunctionWithClosure
    - global scope
createFunctionWithClosure -> Activation Object (not found)
global scope -> Variable Object (found)

The described lookup procedure is for ECMAscript Edition 262 3rd edition. ECMAscript edition 5 has some fundamental changes there.

like image 154
jAndy Avatar answered Sep 24 '22 15:09

jAndy