2009-06-01 14 views
5

私は記事(JavaScript Closures for Dummies)を読んでおり、その1つの例は次のとおりです。 testlistというのと呼ばれているクロージャでローカル変数はどのように参照されますか?

function buildList(list) { 
    var result = []; 
    for (var i = 0; i < list.length; i++) { 
    var item = 'item' + list[i]; 
    result.push(function() {alert(item + ' ' + list[i])}); 
    } 
    return result; 
} 

function testList() { 
    var fnlist = buildList([1,2,3]); 
    // using j only to help prevent confusion - could use i 
    for (var j = 0; j < fnlist.length; j++) { 
    fnlist[j](); 
    } 
} 

testList(); 

、 "未定義のITEM3" と言う警告ボックス。資料では、この説明があります。匿名関数は、それら全てが同じ単一の閉鎖を使用fnlist[j]();ライン上呼ばれ

を、彼らは私が値を持つ1つの閉鎖(内iと項目の現在の値を使用しますループが完了したために3の値があり、itemの値は 'item3'です)。

なぜアイテムは 'item3'の値を持っていますか?私が3になったときのforループの終了はありませんか?終了した場合、項目はまだ 'item2'ではないはずですか?または、testListが関数を呼び出すときに変数項目が再度作成されますか?

+0

リンクするよりも多くのテキストが表示されるバグですか? – CookieOfFortune

答えて

4

あなたが近くにいる...

はなぜ項目は 'ITEM3' の値を持っているのですか?私が3になったときのforループの終了はありませんか?

はい。

終了すると、項目はまだ 'item2'になりますか?

いいえ。この例は少し難解です。ループの最後の反復の間、iが2であるが、それは換言すれば3であるlist配列、の3要素を参照し、item == 'item' + list[2] == 'item3'

またはtestlistという、関数を呼び出すとき、可変項目が再度作成されます?

いいえ、あなたは初めてほぼ間違っていました。私はあなただけitem[2] iが3になったときにループが終了3.

+0

うわー、それはとても簡単です。どのように私はそれをお見逃しですか?全体のスタートカウントがゼロのことは、常に私を台無しにする。ありがとう! – hekevintran

+0

これがjavascriptのクロージャーを理解する唯一の障害物だった場合は、自分自身に背を向けてください!私はその例が不必要に複雑であったと思う。 – Triptych

0

の値を持っていますが、「アイテム」変数が閉鎖に格納され、警告が表示するが、

var item = 'item' + list[i]; 
に設定されていることを逃したと思います

テキスト 'item' +リスト[2]の値。 3番目のリスト項目は3なので、テキストはitem3です

2

list変数は、あなたが言うようにクロージャーに格納されています。

実際にlist変数にアクセスできますが、list[3]にアクセスしようとしています。結局、i変数もクロージャとして格納され、console.log関数が呼び出されると値は3になります。

4

次か前にbuildList内のループが完了したためにザ・:

for (var j = 0; j < fnlist.length; j++) { 
    fnlist[j](); 
} 

...ので、(あなたが各関数を呼び出す)、その時点で、変数itemがそれに最後に割り当てられたものは何でもなります(すなわち、"item3")、i3(最後のi++の操作の結果)であり、list[3]undefinedです。

closure'd関数を呼び出す前に、ループが完了しているということがすべてです。これを防ぐために、あなたはそうのように、新しいクロージャを作成することができます。

function buildList(list) { 
    var result = []; 
    for (var i = 0; i < list.length; i++) { 
    var item = 'item' + list[i]; 
    result.push(
     (function(item, i){ 
      // Now we have our own "local" copies of `item` and `i` 
      return function() { 
       console.log(item + ' ' + list[i]) 
      }; 
     })(item, i) 
    ); 
    } 
    return result; 
} 
+0

@ J-P、素晴らしい応答に感謝します。私は今なぜそれが未定義であったのか理解していますが、なぜあなたが作品の例なのか尋ねることができますfnlistに現在格納されている関数ごとに新しいクロージャが作成されるのはなぜですか? – screenm0nkey

+0

"result.push"の呼び出しの中で宣言され呼び出された関数は、独自のクロージャを作成します。 – Pointy

+0

@ Pointy、それはなぜそれが独自の閉鎖を作成するのですか?それは無名関数なので? – screenm0nkey

2

私は、あなたが不足している点が、iが3で、かつlistのみ0..2のために定義されているため、list[i]がunderfinedされていることだと思います。

関連する問題