Wednesday, October 6, 2010

JavaScript Closure Examples

So I am listening to Douglas Crockford's lecture on JavaScript functions. And I need to get this really straight in my head and separate from Java :-)

Crockford defines "Closure" as follows:
The context of an inner function includes the scope of the outer function.
An inner function enjoys that context even after the parent functions have returned.
Crockford presents the following example that includes a global variable, which I renamed slightly and ran in the Google Chrome console:
var names= ['zero','one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
var global_digit_name = function (n) {
return names[n];
};
global_digit_name(3);
"three"
typeof global_digit_name
"function"
I am using the JavaScript "typeof" operator to inspect what is being generated. Crockford make the point that this function is making use of a global variable, and that global variables are evil, which I guess I go along with; although I wonder if this example isn't already demonstrating closure, i.e. the global variables are just variables in the global function scope that the local function is getting access to, but perhaps that's not how global scope works in JavaScript, but anyway ... before moving on, let's think how we would so the same thing in Java:
static String[] names = {"zero","one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

static String global_digit_name(int n) {
return names[n];
}

public static void main(String[] args) {
System.out.println(global_digit_name(3));
}
Here I am using static scopes to create a "global" variable and a "global" method. I can't assign the method to a variable in Java, so I just call it in the main function. Anyhow, back to the JavaScript example, in the name of removing the evil global variable Crockford the presents a slow alternative:
var slow_digit_name= function (n) {
var slow_names= ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return slow_names[n];
};
slow_digit_name(3);
"three"
typeof slow_digit_name
"function"
slow_names
ReferenceError: slow_names is not defined
So the JavaScript advantage here is that the names variable is safely inside the function and can't interfere with other global variables. The Java equivalent is straightforward:
static String slow_global_digit_name(int n) {
String[] slow_names = {"zero","one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
return slow_names[n];
}

public static void main(String[] args) {
System.out.println(slow_global_digit_name(3));
}
In both Java and JavaScript cases the slowness results from reallocating the array each time the method is called which is a bit wasteful. Now comes the JavaScript example that Crockford labels "closure":
var closure_digit_name= (function () {
var closure_names= ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return function (n) {
return closure_names[n];
};
}());
closure_names
ReferenceError: closure_names is not defined
typeof closure_digit_name
"function"
So again we avoided the nasty global variable, but now the object literal closure_names is not allocated each time. Interestingly I can get definitions of the functions defined so far from the Chrome console:

closure_digit_name
function (n) {
return closure_names[n];
}
slow_digit_name
function (n) {
var slow_names= ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return slow_names[n];
}
Which allows us to see clearly that closure_digit_name is not reallocating the object literal each time. Where I am perhaps confusing myself is that I thought by assigning the return of a call to a function to closure_digit_name that we were turning closure_digit_name into an object, but not according to the Google Chrome console which still gives the type of closure_digit_name as a function. I think it is me just confusing myself. Crockford doesn't mention objects being returned, here's what he says (with my minor edit to make it apply to my example - unfortunately I don't have his colour highlighting):
We assign the return value of the outer function to closure_digit_name. The outer function has now returned, digit_name now contains a function, which is the green function. That green function still has access to names, even though names is a private variable of a function that's already returned. That's closure: one function closes over the variables of another function. This turns out to be one of the most important features in JavaScript; this is the thing that it got amazingly right. This is the thing that makes JavaScript one of the world's brilliant programming languages.
In my own words it seems like we are defining a function on the fly that happens to have a variable and a function, so the following longer version should be exactly equivalent:
var my_function = function () {
var closure_names= ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return function (n) {
return closure_names[n];
};
}
var closure_digit_name= my_function();
which Google Chrome confirms, and gives me the advantage of being able to check the contents of my_function:
my_function
function () {
var closure_names= ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return function (n) {
return closure_names[n];
};
}
Which reassures me slightly as at least I can now see where closure_names is, sort of :-) It really does seem to me to say that by calling my_function() that we get back some sort of object with a function and a variable, but I guess that's part of the JavaScript power, that functions can have other functions and variables, but it does seem slightly odd that the consequence of calling a function is to return a function. Quoting from Crockford's book:
A function always returns a value. If the return value is not specified, then undefined is returned. If the function was invoked with the new prefix and the return value is not an object, then this (new object) is returned instead.
According to which, I would have thought that my_function as I define it above, should return "undefined" and not the function that it contains, but that is what seems to happen. On closer inspection I see that my_function is not just containing the sub-function, it is returning the sub-function, so everything starts to make sense, and the example can be unobfuscated further like so:
var my_function = function () {
var closure_names= ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
var my_sub_function = function (n) {
return closure_names[n];
};
return my_sub_function;
}

var closure_digit_name= my_function();
and Google Chrome confirms for me that this does exactly the same thing, and as far as I know there is no simple equivalent in Java. Interestingly I can't access the closure_names variable from the reference I now have to my_function:
my_function.closure_names
undefined
And I guess that is because this really is a function and not an object ..., but it certainly seems to have an object like nature, at least the way I think about them :-)

Sunday, October 3, 2010

Google App Inventor

Had great fun with Google App Inventor over the weekend. Got my beta invite and was able to do wysiwyg interface design and program creation with my app live updating to the phone. It has a very similar programming interface to Scratch, the program from MIT designed to teach programming to kids. I had been playing with Scratch and others with my 5 year old son, and had been disappointed to hear that Apple yanked a Scratch clone from the iPhone because they don't want any other mechanisms for creating apps other than Objective C.

Would be nice if App Inventors layout interface were as good as interface builder for iPhone in the Xcode, and would be great if you could see the java code that was compiled from the Scratch visual programming. Would be interesting to see if I could use this in the mobile programming class I will teach in the Spring ...

So, great fun, although I still think there could be an easier programming interface that would work well for even younger children. Seems to me that you could be able to do things like move sprites and then capture that activity in a macro format, that would then show up as a procedure that could be manipulated. Maybe Google will open source appinventor and then something like that could be created ...