みんな、クロージャは好きかい!僕は大嫌いさ!スコープがややこしくなるからね!こんな邪悪な機能無くなってしまえばいいのに!
と思いつつも時々便利なのでしみじみ使ってみた。どれくらいしみじみかというと、一晩中くらい。
まず、AS3には二種類のクロージャがある。「メソッドクロージャ」と「関数クロージャ」。何が違うかというと、スコープの扱いが違う。あぁややこしい!
public class Hoge {
private var classFunc:Function;
public function Hoge() {
this.addEventListener(Event.ADDED, this.method);
this.addEventListener(Event.ADDED, function() {
//これは関数クロージャ。このfunctionオブジェクトの持ち主によって実行される。
//この構文の場合、持ち主がいないのでglobalオブジェクトによって実行される。
trace(this); //-->>[object global]
});
var methodFunc:Function = function() {
//これも関数クロージャ。これも持ち主がいないのでglobalオブジェクトによって実行される。
trace(this); //-->>[object global]
}
methodFunc();
this.classFunc = function() {
//これも関数クロージャ。これはHogeクラスによって実行される。
trace(this); //-->>[object Hoge]
}
this.classFunc();
}
public function method(event:Event) {
//これはメソッドクロージャ。常にHogeクラスのインスタンスによって実行される。
trace(this); //-->>[object Hoge]
}
}多分こんなカンジであってる。命名センスについてはほっといてくれ!
んで、こんな使い方をしたいときがある。
public class Hoge extends Sprite {
public function Hoge() {
this.addEventListener(Event.ADDED, function() {
this.visible = false;
//これだけのためにメソッド定義するのってイマイチだし!
});
}
}前述の通りこのクロージャのスコープのthisはglobalオブジェクトなので、visibleなんてプロパティはもってない。なんてことだ。そなら引数で渡してやろう。
public class Hoge extends Sprite {
public function Hoge() {
this.addEventListener(Event.ADDED, (function(owner:Hoge) {
trace(owner); //-->>[object Hoge]
owner.visible = false;
return function(event:Event) {
}
})(this));
}もっとスマートなやり方はないんでしょうか。。。