0

Consider the following code:

var xx=1;
var ff=function(){
  return xx+1;
}
ff();    

var gg=function(){
  return gg.xx+1;
}
gg.xx=1;
gg();

Should there be any clear performance difference between these two approaches? It seems to me that the ff function should perform faster since it references only one variable whereas the gg function references two variables. I am developing a game and want to exploit every possible speed trick that I can.

2
  • There is no closure, the variable resolution (xx and gg) is identical. The second also involves a property lookup so should be slower, but there's no accounting for browser vagaries. Commented Dec 22, 2013 at 23:23
  • Worry more about keeping your data well organised. Performance differences in this area are going to be extremely trivial compared to others - eg driving the DOM. Commented Dec 23, 2013 at 2:06

1 Answer 1

4

This has been asked many times before. The only difference here is that neither example would normally be called a closure, they are simple cases of variable and property resolution.

In the case of:

var xx = 1;
var ff = function(){
  return xx + 1;
}

then within the function, xx must first be resolved on the local variable object, and then on the scope chain. So that's two lookups at least.

In the case of:

var gg = function(){
  return gg.xx + 1;
}
gg.xx = 1;

within the function, gg must be resolved in exactly the same way as the first case (i.e. on the local variable object and then on the scope chain), which again is two lookups. Having found gg, its properties must be searched find xx, which may involve a number of lookups.

Given the above, it's logical to assume the first is faster.

Of course, that's just a logical deduction, performance may actually be counter to that. In some browsers, global variable lookup is faster than local regardless of the length of the scope chain. Go figure.

It is certain that performance will be different in different browsers, regardless of which way it goes. Such performance tweaks (if there is any performance benefit at all) are playing at the margins and should be treated as premature optimisation.

Edit

To code this as a closure requires something like;

var gg = (function() {
  var g;
  return function() {
    gg = function() {
      return g.xx + 1; // Here is the closure
    }

    if (typeof g == 'undefined') {
      g = gg;
    }

    if (typeof g.xx == 'undefined') {
      g.xx = 1;
    }

    return g();
  }
}());

since gg doesn't have a value until the IIFE finishes, so the closure can only be created at that point, the value can only be assigned later, when the function is fist run.

Note that g must still be resolved on the local variable object, then on the scope chain so still two lookups and no gain from the closure (at least no logical gain).

Edit 2

Just to be clear regarding closures:

var xx = 1;
var ff = function(){
  return xx + 1;
}

Does technically not form a closure, but not one worth recognising. The identifier xx is resolved on the scope chain, there are no variables on the scope chain that are accessible by ff when some outer execution context completes. So the closure exists only for as long as the function does and therefore is no more remarkable than lexical scope.

In contrast:

var ff = (function() {

  var closureVariable;

  // This "inner" function has a closure with closureVariable
  // If value is undefined, get (return) the value. Otherwise, set it
  return function(value) {
    if (typeof value == 'undefined') {
      return closureVariable;
    }
    closureVariable = value;
  };
}());

In this case, ff has exclusive access to closureVariable, which is a variable that remains accessible after the function that created it has completed:

// set the value
ff('foo');

// get the value
console.log(ff());  // foo

closureVariable is only accessible by ff (unlike global variables) and persists over numerous calls (unlike local variables). It's this feature of closures that allows them to emulate private members.

Another feature is that many functions can have a closure (or priveliged access) to the same variable, emulating a kind of inheritance.

Sign up to request clarification or add additional context in comments.

15 Comments

"neither example would normally be called a closure" You have a messed-up definition of closure. A closure is any function that uses a variable from an outer scope. Both of those are closures.
@RobG: Just because somebody wrote something does not make it right. en.wikipedia.org/wiki/Closure_%28computer_programming%29 "a closure is a function or reference to a function together with a referencing environment"
@RobG: I believe what I state is consistent with what is said in textbooks and literature. Rather than argue who said what, let's talk about the content. I understand your point of view -- you posit that when a function is created, it does not have access to its lexical environment, and that that environment is magically tacked on when it is "made accessible outside of the function in which it was contained". Whereas I say that it has this access when the function is created.
@RobG: The only difference between the two is when the function is within the scope that created it, and for that, you can explain accessing outside variables as accessing variables already in the stack. So there is no demonstrable difference between what we say. However, which view is simpler? Consider how the runtime would implement this. How would it detect when the function is "made accessible outside of the function in which it was contained"? One case is if it is returned. But it can also be put into some data structure, which may or may not become accessible outside of the function.
@RobG: I disagree. Saying "go read it" is rude as it is implying that other people are not familiar with what is said there. In any case, this discussion is not about JavaScript. General programming terms like "closure" apply to all languages and must be defined in a way that is consistent across languages. Since this is a disagreement over definitions, it cannot be resolved by any article. This is the definition that I have seen everywhere. I accept that you have a different definition, but I do not agree with it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.