Closures and Callbacks!
Today I'd like two snippets of interrelated code and discuss them. We were asked to recreate the functionality of two ubiquitous ruby functions using JavaScript: .each and .map.
Take a look at the snippets below:
Array.prototype.myEach = function( func ) { for(var i = 0; i < this.length; i++){ func(this[i]); } };
Array.prototype.myMap = function( func ) { var result = []; this.myEach( function(el){ result.push(func(el)); }); return result; };
The code functions as you would expect, however viewing the code through ruby colored-glasses it may be difficult to dissect what exactly is going on. Why does myEach not have a return value? Why does myMap pass an anonymous function? How does myEach get access to the result array?
Let's break it down:
myEach is a simple function which takes a different function as an argument. my Each iterates through each element of the array and runs the passed in function once per element. There is no return value -- it just does the work then takes a vacation.
myMap starts by defining a local variable result. result is an empty array that will hold the results of myMap's activities.
myMap's goal is to function much like the .map method functions in ruby. It will iterate over each element in the array, manipulate the element, and store the manipulated element in a new array -- for eventual return.
Our desire here is to use myEach to take care of iterating over each element and calling our desired element. Our problem is that myEach doesn't SAVE the results of its efforts. How do we get around this?
The answer: closures. A closure is a function that has access to variables that it does not define and have not been passed to it.
Here, the anonymous function we pass to myEach is defined within myMap. Consequently, it has access to variables defined in myMap's scope -- specifically the result variable! (through a closure)
Therefore, we can use the anonymous function to instruct myEach to not only run the desired function on each element in the array -- but to push the calculations into result while it's at it.
Here's the resulting code and en example of the output:
var timesTwo = function(n) { return (n * 2); } newArr = [1,2,3].myMap(timesTwo); // newArr = [2,4,6]
Thanks for reading! I hope this helps.






