Archive for the ‘copy’ tag

Javascript Closures

without comments

I am very much a fan of C++11 lambda functions. They’re very useful and make perfect sense to me. In particular I like the “=” and “&” notation to specify if variables from the outer scope are (effectively) copied by value or passed by reference to the closure. Pass by value and pass by reference are fundamental parts of C++ and make good sense to me.

However, for some reason I simply wasn’t grokking how the equivalent functionality works in Javascript. Everything seems to be a reference: how do I “pass” something by value to a function object in Javascript? And even knowing how the answer, why is that?

The Question

Let’s start with a fabricated simple example. It creates 10 functions, each of which appends a number to the end of a result string.


Result:

Analysis: As the results should (it’s run live in your browser, so hopefully they are as expected!) indicate, the above code results in a string of “10″ repeated 10 times. Why is this? Because “i” in the inner function is a reference to the “i” from the outer scope. It is not a copy or passed-by-value into the inner scope. There’s only one object ever named “i” and it’s value is 10 at the time the functions in the “funcs” array are evoked.

Now the question is, how do we get the above code to result in “0 1 2 3 4 5 6 7 8 9″?

The Answer

Let’s quickly look at the answer (which you could probably find in lots of places on the web, but I never found a satisfactory accompanying explanation). To get the value “copied” into the function, you need to wrap the function in outer function invokation which passed in the variable as an argument:

var n = ...;
var f = function() { /* code using n */ };
var g = (function(n) { return function() { /* code using n */ }; })(n);


In the above if “f” is called, it will use the value of “n” at the time that f is called – since it holds a reference to “n”.

In the above if “g” is called, it will use the value of “n” at the time that g was created – since the inner function actually holds a reference the function argument “n”, not the outer n.

Why? In short, when an object is passed as an argument to a function, a shallow copy of that object of the object is made. Thus the inner function refers to the copy at the time of the invokation of the outer function rather than a referring to the object in the original outer scope.

A little less elegant as compared to C++, but the pattern works and allows you “pass by value” into the closure.

Revisiting the Example

Using the above information, let’s now modify the example to print the result we want:




Result:

The key difference between this example and the original example:

  • In the original example, there was 1 object created called “i”
  • In the second example, there were 11 objects created called “i”

In the first example, each function in the “funcs” array refers to that single object called “i”. In this example, each function in the “funcs” array refers to a different object that was created temporarily when the outer, wrapper function was invoked. This ensures that the value of loop variable “i” at the time of the function creation is retained for use when the function is later invoked!


Written by arthur

November 30th, 2011 at 5:02 pm