ActionScript3.0で関数クロージャ使えると便利だよ!
ActionScriptでは、関数クロージャ使う場合と、使わない場合では、だいぶ書き方に差が出る。
関数クロージャ使った方が、綺麗に、短く書けるようになる。
ということで、メソッドクロージャ使ったパターンを紹介するよ!
関数クロージャってなに?っていう人は以下のサイトを読めばわかるかも。
Adobe ActionScript 3.0 * 関数のスコープ
メソッドクロージャとバインドメソッド at AS3S.ORG
その1 イベントのリスナーとして使う
イベントリスナーを作るとき、わざわざメンバとして作ってやるのはめんどくさい。
そんなときは関数クロージャ使えばいいよ!
普通に書いた場合
package { import flash.display.Sprite; import flash.events.Event; public class Main extends Sprite { public function Main():void { addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(e:Event):void { trace("ENTER FRAME !"); } } }
関数クロージャを使用した場合
package { import flash.display.Sprite; import flash.events.Event; public class Main extends Sprite { public function Main():void { addEventListener(Event.ENTER_FRAME, function(e:Event):void { trace("ENTER FRAME !"); }); } } }
関数クロージャを使えば結構コードがすっきりして、可読性が上がる。
その2 スコープとして使う
ASのスコープは関数単位。
Javaとは違ってブロック単位でのスコープはないよ。
つまり関数内では同じ変数を二個作ることは出来ないわけだ。
例えば関数内でfor文を二回以上使いたい場合、はループのための変数名を二個作るか、
変数を使いまわさないといけない。
public function Main():void { var xs:/*int*/Array = []; for (var i:int = 0; i < 5; i++ ) { xs.push(i); } var sum:int = 0; for (var j:int = 0; j < xs.length; j++ ) { sum += xs[j]; } trace(sum); }
この例だとiとjという2つの変数を使っている。
ただ、この書き方は、下のfor文で間違ってiを使ったりして、間違えやすい。
これを関数クロージャでくくってやると、スコープが働くので、
別々の関数クロージャなら同じ変数を宣言しても問題なくなる。
public function Main():void { var xs:/*int*/Array = []; (function():void{ for (var i:int = 0; i < 5; i++ ) { xs.push(i); } })(); var sum:int = 0; (function():void{ for (var i:int = 0; i < xs.length; i++ ) { sum += xs[i]; } })(); trace(sum); }
iを別々の場所で二回宣言しても、コンパイラに怒られることはない。
その3 配列の高階関数の引数として使う
例えば、配列の要素すべてに5を足した配列を作りたいとしよう。
普通にやるなら、for文で回すのが一般解だろう。
var xs:/*int*/Array = [0, 1, 2, 3, 4, 5]; var outs:/*int*/Array = []; for (var i:int = 0; i < xs.length; i++) { outs.push(xs[i] +5); } trace(outs);
しかし、配列にはそれにぴったりな関数が用意されてる。map()だ。
var xs:/*int*/Array = [0,1,2,3,4,5]; var outs:/*int*/Array = xs.map( function(x:int, index:int, xs:/*int*/Array):int { return x + 5; } ); trace(outs);
ちなみにこれはもっと短く書ける。
trace([0, 1, 2, 3, 4, 5].map(function(x:int, ...rest):int { return x + 5; } ));
すっごい短く書けるよ!
配列には他にも、便利な関数が何個もある。
filter()とか、every()とか、some()とか。
ちなみに、map()とか、filter()とか、引数に関数をとる関数を高階関数っていうらしいよ。
関数クロージャ便利だからどんどん使っていこうぜ!