ゆーたんのつぶやき

株式会社ノークリサーチにてIT関連のシニアアナリストとして活動しています。

JavaScriptとActionScript3のthis解決



既に周知のことではありますが、JSとASの
両方を書いたりしていると、うっかりミス
をすることもあるので、備忘録的にメモ..


JavaScriptの場合、thisは実行時のコンテキスト
オブジェクトになります。


var objA = {
name: 'John',
dispName: function() {
alert(this.name);
}
};

var objB = {
name: 'Betty'
};

objB.dispName = objA.dispName;

objA.dispName(); //結果は「John」
objB.dispName(); //結果は「Betty」

一方、ActionScript3はJavaに近くなっており
thisはあくまで元のインスタンスを指します。

public class ClassA {
public var name:String = "John";
public function dispName():String {
return this.name;
}
}

public class ClassB {
public var name:String = "Betty";
public var dispName:Function;
}

import flash.display.*;
import flash.text.*;

public class Main extends Sprite{
public function Main(){
var tfA:TextField = new TextField();
var tfB:TextField = new TextField();

var a:ClassA = new ClassA();
var b:ClassB = new ClassB();

b.dispName = a.dispName;

tfA.text = a.dispName();
tfA.y = 10;

tfB.text = b.dispName();
tfB.y = 40;

addChild(tfA); //結果は「John」
addChild(tfB); //結果は「John」
}
}

ところが、クラスのメソッド定義ではなく
関数型プロパティに無名関数を設定した形
で記述すると、JavaScriptの場合と同様に
なります。

public class ClassC {
public var name:String = "Kathy";
public var dispName:Function = function():String{
return this.name;
}
}

public class ClassD {
public var name:String = "Robert";
public var dispName:Function;
}

import flash.display.*;
import flash.text.*;

public class Main extends Sprite{
public function Main(){

var tfC:TextField = new TextField();
var tfD:TextField = new TextField();

var c:ClassC = new ClassC();
var d:ClassD = new ClassD();

d.dispName = c.dispName;

tfC.text = c.dispName();
tfC.y = 10;

tfD.text = d.dispName();
tfD.y = 40;

addChild(tfC); //結果は「Kathy
addChild(tfD); //結果は「Robert」
}
}

メソッドの場合はインスタンスにバインドされるけれども
関数プロパティとした場合には無名関数がインスタンス
独立して存在しているということですね。確かにコードを
見るとそういう動きが妥当な感じがします。


しかしながら、無名関数の場合でもthisを省略すると
インスタンスにバインドされた状態になります。

public class ClassE {
public var name:String = "Mike";
public var dispName:Function = function():String{
return name;
}
}

public class ClassF {
public var name:String = "Beth";
public var dispName:Function;
}

import flash.display.*;
import flash.text.*;

public class Main extends Sprite{
public function Main(){

var tfE:TextField = new TextField();
var tfF:TextField = new TextField();

var e:ClassE = new ClassE();
var f:ClassF = new ClassF();

f.dispName = e.dispName;

tfE.text = e.dispName();
tfE.y = 10;

tfF.text = f.dispName();
tfF.y = 40;

addChild(tfE); //結果は「Mike」
addChild(tfF); //結果は「Mike」
}
}

上記の場合はコードをパッと見てもバインド
されているというのを見落としてしまいがち
かも知れません。


thisは省略せず、処理内容を動的にしたい場合は
関数型プロパティに代入、静的で構わない場合は
メソッドで定義というのが無難なスタンスかなと
いう気がします。


こういう微妙な動作の違いも面白いですね。