return 関数で参照されていない別の var が foo で定義されている場合、それはクロージャー スコープには存在しません。
これは完全に正確ではありません。変数は、関数自体の内部で (関数コードを見ることによって) 直接参照されていない場合でも、クロージャー スコープの一部です。違いは、エンジンが未使用の変数を最適化する方法です。
たとえば、クロージャー スコープ内の未使用の変数は、DOM 要素を操作しているときに (特定のエンジンで) メモリ リークを引き起こすことが知られています。たとえば、次の古典的な例を見てみましょう。
function addHandler() {
var el = document.getElementById('el');
el.onclick = function() {
this.style.backgroundColor = 'red';
}
}
ソース
上記のコードでは、(少なくとも IE と Mozilla の両方で) メモリ リークが発生しel
ます。これは、参照されていないにもかかわらず、クリック ハンドラ関数のクロージャ スコープの一部であるためです。これにより、ガベージ コレクションが参照カウントに基づいているため、削除できない循環参照が発生します。
一方、Chrome は別のガベージ コレクターを使用します。
V8 では、オブジェクト ヒープは 2 つの部分に分割されます。オブジェクトが作成される新しいスペースと、ガベージ コレクション サイクルを生き残ったオブジェクトがプロモートされる古いスペースです。オブジェクトがガベージ コレクション サイクルで移動されると、V8 はそのオブジェクトへのすべてのポインターを更新します。
これは、世代別または一時的なガベージ コレクタとも呼ばれます。より複雑ではありますが、このタイプのガベージ コレクターは、変数が使用されているかどうかをより正確に判断できます。