Javascriptは多言語と圧倒的に違うのが、イベントの使い方です。
ブラウザ言語であるJavascriptは、サーバー言語とは違い、あらゆる動作イベントに対してのプログラミングができるようになっています。
ちなみに、nodejsはサーバーサイド言語ですが、今回はややこしくなるので、javascript=ブラウザ言語として扱います。
そんな便利なjavascriptで色々なシステム(ホームページやWEBサービス)を構築していると、グローバル変数だけを使っているとwindow直下の変数がゴミだらけになったり、被り変数などでのコンフリクトが発生して、品質低下に繋がるので、基本的にクロージャー構成(ローカル変数構成)での構築をやってしまいますが、
その時に、イベント発火した時にクロージャーの内部変数にアクセスできなくて困っていました。
イベント変数受け渡しの問題点
具体的には、function定義された関数をnewで呼び出してそれぞれの処理をしている時に、その関数内部ではthisによる内部変数(関数)でのやりとりが通常ですが、
クリックやスクロールなどによるイベントで関数を呼び出すとその関数内ではthisが使用できなくなるという問題が発生しました。
ブラウザで表示して関数をイベント実行できるように、htmlも事前に作っておきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<title>javascript instanse</title>
<script type="text/javascript" src="./event.js?3"></script>
</head>
<body>
<h1>JavaScript - Instanse</h1>
<script>
new instanse("test-1");
</script>
</body>
</html>
イベントサンプルプログラムは次の通りです。
;instanse = (function(){
var __ = function(str){
this.str = str;
__event(window , "click" ,this.proc);
this.proc("first");
};
__.prototype.proc = function(mode){
console.log(mode +" : "+ this.str);
};
var __event = function(target, mode, func){
if (typeof target.addEventListener !== "undefined"){
target.addEventListener(mode, func, false);
}
else if(typeof target.attachEvent !== "undefined"){
target.attachEvent('on' + mode, function(){func.call(target , window.event)});
}
};
return __;
})();
この実行結果は以下の通り
first : test-1
[object MouseEvent] : undefined
proc関数への変数の受け渡しもできない上、クロージャー変数も"undefined"になってしまう始末です。
bindを使って解決
上記の2つの問題点、「送り値」「クロージャー変数」を一気に解決できるのがbindを使ったイベント登録です。
下記の様に書き換えるだけで、オールクリアになります。
__event(window , "click" ,this.proc);
↓
__event(window , "click" , (function(){this.proc("click")}).bind(this));
# 結果
first : test-1
click : test-1
非常に素敵ですね。
今回は"__event"という関数を使って便利にイベント登録をしていますが、addEventListnerでも同じ様な書き方で登録できるので、おためしあれ。
解説
基本的にはbind関数を理解していれば、安易にわかると思いますが、過去に記事を書いているので、そのページを参考にみてください。
あまり使わないbind関数調査
要するに、bindの指定変数をクロージャー化してwrapするというような少し複雑な説明になるんですが、よくわからない人は、上記サンプルをそのまま使ってイベント設定するようにすれば、いいと思いますよ。
電子レンジで便利なラップはプログラムでも便利に使えるんですね・・・
0 件のコメント:
コメントを投稿