javascriptの「this」が指すもの

javascriptの「this」が何を指すのかが、ちょっとわかりにくかったのでメモ。

例えば、以下のようなコードは”Taro Yamada”ではなく、”undefined undefined”が表示されてしまいます。(Windows XP IE7で確認)

<html>
<head>
<script type="text/javascript">
var Person = function(first_name, last_name) {
  this.first_name = first_name;
  this.last_name = last_name;
  
  this.displayName = function() {
      function makeName(){
          return this.first_name + " " +this.last_name;
      }
      alert(makeName());
  };
}
</script>
<body>
<script>
var p = new Person("Taro", "Yamada");
</script>
<input type="button" onclick="p.displayName();" value="display">
</body>
</html>

これは、this.display中の下請け関数makeNameでは、thisがPersonオブジェクトを指していないためです。実は、makeName中のthisはグローバルオブジェクト(windowオブジェクト)を指してしまっています。

意図どおりに動作させるためには、次のように書き換えます。

<html>
<head>
<script type="text/javascript">
var Person = function(first_name, last_name) {
  this.first_name = first_name;
  this.last_name = last_name;
  
  this.displayName = function() {
      var me = this;
      function makeName(){
          return me.first_name + " " +me.last_name;
      }
      alert(makeName());
  };
}
</script>
<body>
<script>
var p = new Person("Taro", "Yamada");
</script>
<input type="button" onclick="p.displayName();" value="display">
</body>
</html>

this.displayName中でthisの値をmeに退避し、makeNameではme経由で変数を参照するだけです。こうすることで、makeNameは正しくfirst_nameとlast_nameを参照できます。

JavaScript: The Good Parts中にも、内部関数でのthisが、呼び出し元である外部関数のthisと異なってしまうのは設計ミスとの記載がありました。

ちなみに、この本では、thisの値をthatという名の変数に退避させています。僕はGoogle Maps API関連のライブラリで使われている”me”を良く使います。意味的にもmeの方がしっくりくるかと。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です