Я бы сказал так. Например, когда в теле функции используется переменная объявленная в вышестоящей функции, то переменная будет удерживаться до тех пор пока не отработает внутренняя функция - т.е. внутрення функция замкнёт на себя переменную.
Например (setTimeout иллюстрирует любую асинхронную операцию):
function func1() {
var myVar1 = 100;
setTimeout(function() {
console.log(myVar);
}, 1000);
}
func1();
Здесь, анонимная функция переданная в setTimeout замыкает на себя переменную myVar, а если бы этого не происходило, то в консоль вывелось бы undefined, т.к. переменная была бы уничтожена.
Использовать можно, например, для создания колбэков с сохранением контекста:
/// Некорректный вариант, выведет 3 3 3
for(var i = 0; i < 3; i++) {
setTimeout(function() { console.log(i) }, 1000); // Потому что на момент вызова колбэка цикл уже отработает и значение i будет максимальным
}
/// Выведет 0 1 2 т.к. текущее значение переменной i для каждой итерации передано аргументом в функцию в которой его замкнула другая функция
for(var i = 0; i < 3; i++) {
var cb = (function(value) {
return function() { console.log(value) };
})(i);
setTimeout(cb , 1000);
}
Последний код делает то, что сегодня уже можно сделать с помощью bind (но в моё время bind'а не было):
for(var i = 0; i < 3; i++) {
setTimeout(function() { console.log(this); }.bind(i) , 1000);
}