[PR]
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
プログラミング、3DCGとその他いろいろについて
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
最近letキーワードを使うとTypeScriptでクロージャのforのインデックス変数キャプチャを簡単にできることを知りました!実はそこそこ昔からあったようですが忘れないためにもメモします。
TypeScriptでは(TypeScriptに限った話ではありませんが)、ループのインデックスをクロージャの中でそのまま使うと変な値になってしまいます。
var getNumbers: (() => number)[] = []; for (var i = 0; i < 3; i++){ getNumbers.push(() => i); } for (var getNumber of getNumbers) { document.writeln(getNumber() + "<br>"); }
3 3 3
変です!0 1 2と表示しようとして「0から2までの数字をそれぞれ返す関数3つ」の結果を表示したはずなのに、そのどれでもない3が表示されています!しかも3回も!!!
これは、3つの関数が実は同じ1つの変数を返すからで、ループのインデックスiが最後に3になったために、3つの関数すべてが3を返してしまったのです。上書きされてしまったので最後に保存したデータしか残っていないという状態です。
この問題を解決するには、3つの関数が違う別々の変数を返すように書き換えなければいけません。上書きするのではなく、別の変数にデータをとっておくのです。
var getNumbers: (() => number)[] = []; for (var i = 0; i < 3; i++){ (() => { var index = i; getNumbers.push(() => index); })(); } for (var getNumber of getNumbers) { document.writeln(getNumber() + "<br>"); }
0 1 2
うまくいきました!前回は同じ変数を返していたので同じ数字が3連続してしまいましたが、今回は変数を3つの違う変数にコピーしたので、きちんと値が上書きされずに保存されています。
ところがこれにはもっとかんたんな解決策があって、それはTypeScript1.5から導入されたletキーワードです。実際にはJavaScript時代からあったそうですが、普及しなかったようです。
var getNumbers: (() => number)[] = []; for (let i = 0; i < 3; i++){ getNumbers.push(() => i); } for (var getNumber of getNumbers) { document.writeln(getNumber() + "<br>"); }
0 1 2
うまくいきました!こっちのほうが上の例よりかんたんなのでこっちを使いたいですね。
letはブロック内でのみ変数が生きているというような意味なので、i=0のときとi=1のときでiが同じ名前の別物になっています。