Shut the fuck up and write some code

グダグダ言わずにコードを書きたいブログ

Javascriptにおけるthisスコープの委譲

最近Javascript書きはじめました。大昔にwebの仕事をしてたときにちょろっと書いてましたが、その時からすでに死に体でしたけど、近年はAJAXやらなんやらで復活モードに。でも携帯業界では全く関係のない話でw。かと思いきや、最近はiPhoneでもHTML5動きますし、携帯でも対応状況が進んできています。
2009年夏モデル以降14機種におけるiモードブラウザの一部機能の再有効化について


んで早速やってるところではまった部分をメモ。


クラスを作ってその中でイベント処理を行おうとするとどうもスコープが狂います。試しにスコープを参照するサンプルを書いてみました。

var obj;
var msg="Global"

function init(){
	obj=new testSetInterval();
};

function testSetInterval(){
	
	this.msg="testSetInterval";
	this.id_Event=null;
	
	this.setEvent();
	
};

testSetInterval.prototype.getMsg=function(){
	return this.msg	
};

testSetInterval.prototype.loopEvent=function(scope){
	console.log("msg:"+this.msg);
};

testSetInterval.prototype.setEvent=function(){
	this.id_Event=setInterval(this.loopEvent,1000);
};


これで出力結果は

msg:Global

となります。どうもsetIntervalの実行元が違うみたいで、クラス内でprivateな変数を参照してイベント処理を行うには、実行元をきちんと委譲してやらないとだめみたいです。これがEcmaScriptの仕様かあ・・・Flashと同じですな。Flashは最初からDelegateのクラスが用意されてますけどJavascriptはそんなものが無い。


http://www.fladdict.net/blog-jp/archives/2005/09/this.php
こちらを参考に処理を修正・追加。

testSetInterval.prototype.setEvent=function(){
	var myfunc=this.loopEvent;
	
	myfunc=createDelegate(this.loopEvent,this);
	this.id_Event=setInterval(myfunc,1000);
};

/* 委譲処理 */
function createDelegate(func, thisObj){

	var del = function(){
		return func.apply(thisObj, arguments);
	};
	
	//情報は関数のプロパティとして定義する
	del.func = func;
	del.thisObj = thisObj;
	return del; 

}


これで出力は

msg:testSetInterval


となります。委譲部分はユーティリティ化したほうが便利ですね。