WebEngine

だらだらと綴る技術系メモ

javaScriptのthis

thisイコール「自分自身」からの脱却


先にコードとコンソール(開発者ツール)での結果を出します。

<div id="test_zone">
  <button id="test_button">テストボタン</button>
</div>
$(function() {

  "use strict";

  console.log("1 : " + this);

  // Testオブジェクト
  var Test = function(score) {
    console.log("2 : " + this);
    this.score = score;
}

  // メソッドはプロトタイプ宣言で
  Test.prototype = {

    buttonOn : function() {
      console.log("3 : " + this);
      console.log("test : " + this.score);

      $("#test_zone").on({
        "click": function() {
          console.log("4 : " + this);
        }
      }, "#test_button");

    }

  };

// -- main --
var test = new Test(55);
test.buttonOn();

});
結果
1 : [object HTMLDocument]
2 : [object Object]
3 :[object Object]
test : 55
4 : [object HTMLButtonElement] // ボタンをクリック後


番号順に説明していきましょう。

1はグローバルなので、オブジェクトはHTMLDocument、つまりwindowを指しています。

2はTestオブジェクト(Testクラス)内なので、Testオブジェクト自体を指しています。

3はbuttonOnメソッド内。結果がobject Objectでわかりづらいので、Testオブジェクトの プロパティであるscoreをthisで呼びしています。scoreがthisで呼びせている、ということ は、つまり、thisにはTestオブジェクトが入っていることを意味しますね。

問題は4です。4でのthisは、HTMLButtonElementを指しています。DOMのボタン を示しているのです。

なぜか。それは、javaScriptでは関数自体が独立したオブジェクトであり、thisは関数を 定義したオブジェクトに属するものではないからです。(この説明は誤解を招くかもしれませんね。自分でも ちょっと自信ないです)

で、結局thisがなんなのかと言うと、その関数やメソッドを呼び出したオブジェクトが入っているというイメージが良い かもしれません。
4では、jQueryのonメソッドのclickメソッドを呼び出したbuttonElementがthisに 入っていたわけです。


上記の場合の解決策

上記の場合で、onメソッド内でTestオブジェクトを参照したい、という場合があります。そのような場合は、 一旦、別変数のなかにthisを格納することで解決できます。下記ではselfという変数 のなかにthisを格納しています。

buttonOn : function() {
  console.log("3 : " + this);
  console.log("test : " + this.score);

  var self = this;

  $("#test_zone").on({
    "click": function() {
      console.log("4 : " + this);
      console.log("5 : " + self);
      console.log("test : " + self.score);
    }
  }, "#test_button");

}
5 : [object Object]
test : 55


Testオブジェクトのscoreselfで呼び出せているので 5のobject Objectの正体がTestオブジェクトであることがわかります。 成功ですね。

参考

applycallを使うとthisを自由自在に操ることができる らしいです。詳しくは以下を参照してください。