this の指す内容に注意、bind() のサンプル
概略
2022年追記: bind() はアロー関数に置き換えられます
bind() も IE 時代までの昔話になっています。
IE を気にしない JavaScript (ES2015 以降) では アロー関数 を多用します。 アロー関数を使うと this が何を指してるかの面倒な話がなくなるので bind() を書く必要がなくなります。 また、引数の末尾に event が自動的に付くといった暗黙の話もなくなります。
概略
JavaScript でイベントリスナーの処理をしたり、 class のオブジェクトを作ってクラス内の関数 (メソッド) を this.関数名() で呼び出すときに、 しばしば関数が見つからないエラー (undefined で TypeError) が起こることがあります。 this の指しているオブジェクトが異なるため発生します。 このようなときには関数を呼び出す側で this が何を指しているのか bind() で指定します。
Java や C# のクラスやメソッドや this の使い方に慣れている人も必ずはまる話なので 参考にどうぞ。同じ感覚で扱おうとしたら必ず泥沼にはまります・・・。
this 違いでエラーが起こる
- TestJS_this_object01.html
連想配列に関数を付け、this でアクセスするサンプル。
JavaScript: this
JavaScript では this の意味が Java や C# と異なります。 処理がどのように呼び出されたか状況に応じて this の指しているオブジェクトが変わることがあります。IE 時代までの JavaScript では this が何を指すかを明示するときに bind() を 使用していました。
近年はアロー関数を使うと bind() による明示が不用になります。
また、this を気にする話が大幅に減ります。
アロー関数: 「アロー関数は this を束縛しない」
- TestJS_this_class_arrow01.html
span タグにクリックイベントを付けるサンプル。
bind() のサンプル
- TestJS_function_map01.html
マップ {} にクラスのメソッドを並べて処理する例。
イベント処理の例
table td にイベント処理を付ける例。
JavaScript イベント処理 (1)
- TestJS_event_table_td_bind01.html
onclick= でいろいろ。 - TestJS_event_table_td_bind02.html
addEventLisnter() でいろいろ。 - TestJS_event_table_td_bind03.html
table の td にイベントリスナーをつける例。 イベント処理一式をクラス化している場合。 this の混乱など、トラブルが起こりやすい。
JavaScript イベント処理 (1)
td.onclick = function(){ onclickTd(this); }; ではなく、下のようにした場合。 1) td.onclick = onclickTd; td.addEventListener("click", onclickTd); 上の記述は関数のある場所(関数ポインタ)をセットしています。 その場では実行しません。 onclickTd(param) の引数 param はマウスイベントになります。 呼び出し側でイベントの変数名を明示しなくても、暗黙で渡されます。 onclickTd() 内の this は td になる点に注意。 this は window オブジェクトではない点に注意。 onclickTd() 内で他の関数を呼んで未定義(undefined)エラーが出る場合は、 たいてい this 違いが原因です。bind() で this が何を指しているのか の明示が必要です。下の話に続く。 2) td.onclick = onclickTd.bind(this, td); td.addEventLisnter("click", onclickTd.bind(this, td)); bind() を付けて引数を渡します。 (補足)bind() は IE8 など古いブラウザで使えませんでした。 td.onclick = function(){ onclickTd(this); }; とほぼ同じです。 関数 onclickTd() の引数は td になります。(暗黙のうちにマウスイベントも 引数の末尾に追加される)。 bind() の最初のパラメータの this は関数onclickTd()内の this が何を 指すかを指定します。 このサンプルの場合は関数 onclickTd() 内の this は window になります。 もし、アプリケーションのオブジェクト app があり、 onclickTd.bind(app, td); とすれば、 関数 onclickTd() 内の this は app、引数は td (とマウスイベント)になります。 ・暗黙のうちにつくマウスイベントの引数は、暗黙に頼らず明示した方がいいかも?。 暗黙に頼って省略すると誤解・錯覚の原因になりやすいです。
参考: bind() がなかった時代のコード (IE8以前)
古い JavaScript で下のような様式のコードが出てくることがあります。 bind() がなかった時代の独特な書き方です。 現在はこのように書く必要はありません。
var obj = new ( function(td){ this.td = td; this.callback = function(){ onclickTd(this.td); }; } )(td); //最後の(td)はコンストラクタに渡す引数