Simply speaking, a closure is an expression with free variables. The real role of a free variable depends on its referencing lexical environment. Programming languages supporting closures usually provide first-class functions. Creating a function isn't equal to creating a closure. If a function's free variable is bound to the referencing lexical environment, the function is called a closure.
So, what's a free variable? For a function, a free variable isn't a local variable or a parameter. Like a local variable or a parameter, a free variable's scope is within the enclosing function. It's a bound variable.
Is there a vernacular wording? Um...
For example:
function init() {
var local = 10;
setInterval(function() {
alert(new Date() + ': ' + local);
}, 3000);
}
window.onload = init;
var local = 10;
setInterval(function() {
alert(new Date() + ': ' + local);
}, 3000);
}
window.onload = init;
If you only look at the bold part of the above example, the variable local is meaningless. The variable local is a free variable for the anonymous function. The enclosing function of the anonymous function, however, declares a variable local, so the variable local of the enclosing function is bound to the anonymous function.
The lifetime of a local variable should ends after the function is executed. In the above example, the function which registered the onload event will be called after all page resources are loaded. After that, it seems that the lifetime of the variable local ends. However, the free variable local of the anonymous function passed into setInterval binds the variable local of the enclosing function. The lifetime of the variable local is extended. While the anonymous function passed into setInterval exists, the variable local exists.
This is like, the variable local said it'll love init until seas run dry and rocks crumble, but it left init for the anonymous function now...XD
So, how to use closures? One of the common applications is creating private scopes in JavaScript. We know JavaScript is a prototype-based language. Those users familiar with class-based languages always want to simulate classes and encapsulate private members. JavaScript doesn't have a private keyword. We can use closures to simulate this feature. For example:
function Account(bal) {
var balance = bal;
this.getBalance = function() {
return balance;
};
this.deposit = function(money) {
if(money > 0) {
balance += money;
}
};
}
var account = new Account(1000);
account.deposit(500); // OK
account.getBalance(); // OK
account.balance = 1000; // Error
var balance = bal;
this.getBalance = function() {
return balance;
};
this.deposit = function(money) {
if(money > 0) {
balance += money;
}
};
}
var account = new Account(1000);
account.deposit(500); // OK
account.getBalance(); // OK
account.balance = 1000; // Error
The above is a basic example about simulating a class. The last line will cause an error because the account object doesn't have a balance property. With some details ignored, the code var account = new Account(1000) will do something like the following:
var account = {};
Account.call(accoount, 10000);
Account.call(accoount, 10000);
In my previous article, I've talked that a function is an object in JavaScript and can own methods. In JavaScript, every function object has a call method. The first parameter of the call method accepts an object which will be referred by this in the called function. The second parameter accepts an argument which will be passed to the first parameter of the function object. In other words, according to the Account function defined in the above, when using the call method to call the Account function, we add a getBalance property and a deposit property on this - the object passed as the first argument of the call method. Those two properties refer to an anonymous function respectively, and those two anonymous functions bind the balance variable. That's, they create a closure respectively. Therefore, when calling those two functions through the getBalance and deposit properties of the account object, you can access the balance variable.
The account object, however, doesn't have a balance property. The balance variable is a local variable of the Account function, so you can't access it directly. This satisfies our requirement about creating private scopes.
It seems the balance variable can live in multiple closures. By analogy, it's dating with many functions at the same time...XD
With all the above, we roughly know basic concepts and applications about closures. I don't want to dive into more applications about closures in JavaScript. If you want to know more about that, take a look at JavaScript Essence: Closures.
We'll discuss how different languages support anonymous functions and closures to draw out considerations about introducing Lambda syntax into Java. The next article will take a look at how Python 3 supports first class functions and closures.