I have been a Java developer since 1995, before that I worked in C++. So my language background is primarily statically-typed and object oriented. In the last several years, I’ve been involved in a number of projects that use JavaScript. I’ve come to recognize that JavaScript is a very powerful language in its own right — but it is dramatically different from the languages that I am used to. One of the features of JavaScript that was a mystery to me is closure.
Closure has no direct equivalent in my native language Java so it took a great deal of reading and experimentation for me to come to grips with this concept. The simplest description I can give is this.
In a closure a variable declared in an outer function is visible to an inner function even if the inner function’s lifecycle is longer than that of the outer function.
Here is an example using the Apache Cordova (PhoneGap) API. The phone Cordova API allows you to package HTML5/CSS/JavaScript applications natively for a number of mobile platforms. It also provides a JavaScript API to wrap many of the native device features like the accelerometer. This example shows a closure.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function startWatch() { var previousReading = { x: null, y: null, z: null }; navigator.accelerometer.watchAcceleration( function (acceleration) { // use previousReading value here }, onError, { frequency: 500 } ); } |
In this example the startWatch() function declares a variable previousReading and sets its x, y and z members to null. The three values will be used to represent acceleration in meters per second squared. The function then calls navigator.accelerometer.watchAcceleration(), passing in an anonymous callback for success. The anonymous callback defined on line 7 in the source code will be called at a rate of once every 500ms and it will compare the current acceleration with previousReading then update previousReading with the current acceleration.
The code is relatively straightforward except for one important detail previousReading was declared in the scope of the outer function startWatch. But the anonymous inner function (on line 7) will be called repeatedly even after the outer function is out of scope! What happens here is that the inner function keeps a reference to any values in the outer scope that it will need when it is invoked.
For those of you who are Java programmers, don’t think you are immune from this discussion. Closures are on the proposed feature list for JDK 8.