2009-08-23

JavaScript: Introduction to closures

This is an introduction to closures in JavaScript. It is intended for JavaScript beginners and belongs to a small series of (future) blogs for JavaScript beginners.

Closures are an important concept in modern programming languages, and one should be able to understand and use them well.

Closures are functions which reference (i.e. use) variables that are defined outside of those functions. This is not an exact definition, but it will help for the following examples.

In JavaScript, closures are usually realized as functions which are defined of other functions.

Have a look at the following code:

1: function foo() {
2:   
3:   function gee() {
4:     return 1;
5:   };
6:   
7:   return gee();
8: }
9: 
10: print( foo() );

The function foo contains an inner function gee. The ability of a function to have inner functions is an interesting point. In other languages like in Java that is not possible. gee is our first closure here.

The function – or the closure - gee returns the number 1, and the method foo returns the value, that gee returns, i.e. 1. So far nothing special…

By the way, the print method at the bottom of the code, is a method of the Aptana JavaScript library. You can download the Aptana Studio here.

The output of the code above is

1

Now check this code:

1: function foo() {
2:   
3:   var a = 2;
4:   
5:   function gee() {
6:     return a;
7:   };
8:   
9:   return gee();
10: }
11: 
12: print( foo() );
2

This time the method gee uses a variable which has been defined outside of gee, but inside of foo. This is an important feature. The variable a is not a global variable, because it has been defined by using the keyword “var”, but the scope of visibility of this variable contains everything inside of the foo method, and sowith the function gee.

Please keep in mind that from within an function which is defined inside of another function, all variables which are defined in the outer function can be used.

1: function foo() {
2:   
3:   var a = 2;
4:   
5:   function gee() {
6:     return a;
7:   };
8:   
9:   a = 10;
10:   
11:   return gee();
12: }
13: 
14: print( foo() );
10

This time the variable a is defined, then gee, then the value of a is changed. What happens here, is that gee gets a reference to the variable a, so the value 2 is not copied somehow within the function definition of gee (then 2 would be printed), but gee gets a reference to the variable a, so 10 is printed.

1: function foo() {
2:   
3:   var a = 2;
4:   
5:   function gee() {
6:     
7:     var b = 3;  
8:     
9:     function hii() {
10:       return a * b;
11:     }    
12:     
13:     return hii();
14:   };
15:   
16:   a = 10;
17:   
18:   return gee();
19: }
20: 
21: print( foo() );
22: 
30

Now we have three functions which are somehow combined. The same principles as above work now, so the function foo and therefore hii return 3 times 10.


The following example shows that an inner function can also access the parameters of the outer function.

1: function foo( a ) {
2:   return function() {
3:     return a * 2;
4:   };
5: }
6: 
7: print( foo(1) );
8: print( foo(1)() );

And one can see that foo(1) returns what comes after the return statement, i.e. the anonymous, inner function. As it is common in JavaScript, the toString method of a function returns the source code of that function. And as foo(1) is a function, we can call this function by adding (), so that we have foo(1)(), which generates the output “2”.

function () {

    return a * 2;
}
2

Now we have two inner functions (or closures), so that we can call the inner-most function with three parentheses: foo(1)()(). That means, 1 is given to a, then the first inner function is called which has a local variable b, and finally the inner-most function is called which returns the result 6.

1: function foo( a ) {
2:   return function(){
3:     var b = 3;
4:     return function(){
5:       return a * 2 * b;
6:     };
7:   };
8: }
9: 
10: print( foo(1)()() );
11: var f = foo(1);
12: var g = f();
13: print( g() );
6
6

One can also see that one can assign a function to a variable, like f, then call the function by f(), and assign this to a variable, like g, which then can be called by g() - nothing very complicated, just a little bit unusual for people who come from other languages like Java.

The following code example shows a function foo which returns a closure. That closure is again returned to a variable with a more meaningful name as in the examples above.

1: function foo( a ) {
2:   return function( b ) {
3:     return a * b;
4:   };
5: }
6: 
7: print( foo(2)(5) );
8: 
9: var doubleIt = foo(2);
10: 
11: print( doubleIt( 1 ) );
12: print( doubleIt( 2 ) );
13: print( doubleIt( 3 ) );

This example returns the following numbers, i.e. twice the value of the input.


4
6

The interesting point is that one can give the closure foo(2) a new and more meaningful name, so that doubleIt seems to be like a new function which can used in the program later.

It is like converting a given API to something more specific and more useful in the current application or the current context.

The following example shows this again with a function that simply calculates the sum of two numbers, but implemented by a closure.

1: function add( summand1 ) {  
2:   return function( summand2 ) {
3:     return summand1 + summand2;
4:   }
5: }
6: 
7: var threeAnd = add( 3 );
8: var fourAnd  = add( 4 );
9: var fiveAnd  = add( 5 );
10: 
11: print( threeAnd( 2 ) ); // 5
12: print( fourAnd(  2 ) ); // 6
13: print( fiveAnd(  2 ) ); // 7

The output is of course:

5
6
7

The three closures have meaningful names which say what the closure is going to do. In such a way you can easily create new "functions" based on already existing functions or closures.


 

Technorati: , ,

2009-08-13

Java: char to int

Today I found some code (in a current project of a company), where they convert a Java char to an int like this:

int x = Integer.parseInt( String.valueOf( c ) );

where c is a char like '0', '1', ... (i.e. a digit as a char).

I would suggest to make a conversion like:

int x = c - '0';

That's easier and probably faster...