Закрытие - это просто ссылка на функцию, связанную со ссылкой на включающую запись области действия . Итак, в вашем случае:
setTimeout(function(){
То есть функция, которая закрывается, и область, в которой она выполняется, является промежуточной записью области текущего выполнения foo. Когда вы звоните:
foo(1)
создается новая запись области с a
, равной 1
, обычно эта запись отбрасывается, когда foo заканчивает свое выполнение, но поскольку замыкание сохраняет ссылку на нее, этого не происходит. Теперь, когда тайм-аут заканчивается, замыкание выполняется, и ссылка на замыкание теряется, поэтому ссылка на вложенную запись области видимости также теряется, и a
, наконец, собирается сборщиком мусора. Когда вы вызываете foo
несколько раз, создается несколько записей и замыканий, поэтому a
может оценивать разные значения в обратных вызовах, поскольку они разрешаются в разные записи.