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の方がしっくりくるかと。