【JavaScript】prototypeを使ったfunctionでthisの値を取得できない

このQ&Aのポイント
  • JavaScriptのprototypeを使って宣言したfunctionでthis.の値が取れない問題が発生しています。
  • 以下のHTMLコードでは、開いた時に'aaa'がアラートされるつもりで作られていますが、結果としてundefinedがアラートされます。
  • この問題を回避するためには、alert(this.val)の代わりにalert(h.val)と記述することができますが、記述方法に違和感を感じるかもしれません。
回答を見る
  • ベストアンサー

【javascript】prototypeを使って宣言したfunctionでthis.の値が取れない

以下HTMLは開いた時に'aaa'がアラートされるつもりで作りました。 ※行頭は全角スペースです。 <html> <head> <script type="text/javascript"><!-- function hoge(){  this.val ='aaa'; }; hoge.prototype.func = function(){  alert(this.val); }; h = new hoge(); if(window.addEventListener){  window.addEventListener('load', h.func, false); }else{  window.attachEvent('onload', h.func); } //--></script> </head> <body> </body> </html> 結果は、undifindがアラートされました。 alert(this.val); を alert(h.val); とベタに記述すれば回避できますが、ちょっと違和感を感じます。 このような場合、どのような記述がベターなのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

----------Sample---------- function objA(){  this.val ='objA'; } objA.prototype.sayval = function(){  alert(this.val); }; var A = new objA(); A.sayval(); //(1): 'objA' var objA_sayval = A.sayval; objA_sayval(); //(2): undefined var B = {sayval:objA_sayval, val:'objB'}; B.sayval(); //(3): 'objB' //引数を実行するだけの関数。 function run_func(f){ f(); } run_func(objA_sayval); //(4): undefined run_func(A.sayval); //(5): undefined run_func(function(){A.sayval();}) //(6): 'objA' --------Sample End-------- (1) 期待通り'objA'がアラートされる。 (2) 関数sayvalがAから切り離されるのでundefinedになってしまう。 (3) 関数sayvalがBと結びつくので'objB'がアラートされる。  つまり .sayval の左のオブジェクトが関数sayval内でのthisになる。 (4) (2)と同じ理由でundefinedになってしまう。 (5) (4)と同じ理由でundefinedになってしまう。  EventListenerに渡した時うまくいかないのもこのため。 (6) A.sayval();を実行するだけの関数を作ってrun_funcに渡すと期待通り'objA'がアラートされる。 今回の場合(6)の様にすればうまくいくと思いますが、 場合によってはもう一工夫必要な場合もあります。 ([参考]の1つめなど) [参考] DOMのJavaScriptイベントハンドラは引数が固定されている、という制限を回避する方法 - IT-Walker on hatena http://d.hatena.ne.jp/Syunpei/20070605/1181035316 prototype.jsのbindを理解する - cloned.log http://d.hatena.ne.jp/cloned/20070301

kingfruits
質問者

お礼

Wernerさん ご回答ありがとうございます。 これで三度目のご回答です。いつもありがとうございます。 以下の様に記載する事で解決しました。 <html> <head> <script type="text/javascript"><!-- function hoge(){ this.val ='aaa'; }; hoge.prototype.func = function(){ alert(this.val); }; h = new hoge(); if(window.addEventListener){ window.addEventListener('load', function(){h.func();}, false); }else{ window.attachEvent('onload', function(){h.func();}.func); } //--></script> </head>

関連するQ&A

  • 下記コードのようなオブジェクトとかprototypeとかを理解するヒントを教えてください!

    <html> <head> <meta charset="utf-8"> </head> <body> <script type="text/javascript"> var hoge = function(){ //▼ function testFunc(n){ } testFunc.prototype.init = function(c){ alert(c); }// end func return{ testFunc:testFunc } }(); var u = new hoge.testFunc(); u.init("あああ"); </script> </body> </html> ---------------------------------------------------- ここ数日いろいろ弄っているのですが、 いまいちピンと来ない感じです。 何か、参考になるようなスクリプトやポイントなどありましたら、 ご紹介いただけると幸いです。 よろしくお願いいたします。

  • 【javascript文法】 prototype.js Ajax.Request onSuccess:に指定するfancitonの書き方

    以下HTMLは開いた時に'2'がアラート、続いて'hello world'がアラートされるものです。 動作的には期待どおりに動きますが、記述方法に難を感じています。 課題としては、Ajax.RequestのonSuccess:に指定するfancrionをprototypeを使って 宣言したfunctionで且つ、引数を与えたいです。 (Ajax.Requestが返してくる引数も使いたい。) 表現が下手ですみません。 ※行頭は全角スペースです。実際に機能させる為には  半角に修正もしくは行頭スペースは削除して下さい。 <html> <head> <script type="text/javascript" src="prototype.js"></script> <script type="text/javascript"><!-- function http(){  this.val=1; }; http.prototype.request = function(){  var url="/ruby/hello.cgi"; //実際に検証する為にはwebサーバにこのcgiを置く必要あり  new Ajax.Request(url, {   method:"get",   onSuccess: function(h){r.processRequest(h,1);}   /* ↑http.prototype.requestの中なので、r.ではなくthis.processRequest(h,1)と記述したい*/  }); }; http.prototype.processRequest = function(h,arg){  alert(this.val+arg);  alert(h.responseText); }; var r = new http(); r.request(); //--></script> </head> <body></body> </html> 以下"/ruby/hello.cgi"の例 #!/usr/bin/ruby puts "Content-Type: text/html\n\n" puts "hello world" ※実際に実行する場合はprototype.jsが必要です。 これで、期待通りの結果が得られるのですが、コメントに記載したように、 http.prototype.request = function()の中でonSuccess:に指定する関数が、 this.と記述できず、r.と記述しないと動作しません。 http.prototype.request = function()の中で、 ~~~~~~~~~~~~~~ http.prototype.processRequest = function(h,arg) ~~~~~~~~~~~~~~ を使うのですから、 r.processRequest(h,1)ではなく、 ~ this.processRequest(h,1) ~~~~ と記述したいです。 因みに同じような質問を http://oshiete1.goo.ne.jp/qa4663141.html でしており、この『応用』だとも思うのですが、名案浮かばずです。 このような場合、どう記述するのがベターなのでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • AJAX
  • JavaScriptのタイマーについて

    JavaScriptのタイマーについて上手く動作しないので質問させて頂きます。 <仕様>  3秒後に「aaa」のメッセージを表示させる。  5秒後に「aaa」のメッセージを表示させる。 <現在の状況>  3秒後に「aaa」のメッセージを表示し、その後は応答なし。 <ソース> 以下を参照ください。何が悪いのでしょうか? <HTML> <HEAD> <SCRIPT Language="JavaScript"> <!-- timerID = 10; function func() { alert("aaa"); } function init() { timerID = setTimeout("func()", 3000); timerID = setTimeout("func()", 5000); } // --> </SCRIPT> </HEAD> <BODY onload="init()"> </BODY> </HTML>

  • javascriptで印刷ダイアログを出力すると同時に

    javascriptで印刷ダイアログを出力すると同時に setTimeouで一定時間後にアラートを表示していたのですが、 IE8では印刷ダイアログが表示されている時はタイマーが止まってしまうようです。 また、IE6では動作しました。 なにか解決方法はないでしょうか? 以下がサンプルソースです。 <html> <head> <title>setTimeout</title> <script type="text/javascript"> function aaa() { alert("タイムアウトしました。"); } function func() { setTimeout("aaa()", 5000); window.print(); } </script> </head> <body onload="func()"> aaa </body> </html>

  • コンストラクタとプロトタイプについて

    ネットで検索したりして調べているのですがいまいちわからなかった箇所が あるので質問させていただきます。 コンストラクタで設定するのとプロトタイプで設定する違いがいまいちわかりません。 例えば function Test { this.prop = hoge; } Test.prototype.prop1 = hogehoge; の場合 コンストラクタのほうが優先されてhogeがでるのはわかるのですが 下記の場合はプロタイプのほうが優先されてhogehogeと出てしまうのは どうしてでしょうか? <script language="javascript"> <!-- //コンストラクタ function Test(){alert("hoge"); } //prototypeでセット Test.prototype=alert("hogehoge"); //オブジェクト作成 var TEST = new Test(); window.onload=TEST; --> </script>

  • イベントリスナーの部分を関数にしたい

    イベントリスナーの部分で、「load」以外に「change」も必要になったので関数にしたいのですが、 引数の関数の指定方法がわかりません。 どうすればいいのでしょうか。よろしくお願いします。 【イベントリスナーを関数にする前】 function hoge(){ this.view = function(){ var _this = this; window.addEventListener( 'load',function(){ _this.foo()}, false ); } this.foo =function(){ var txt = document.createTextNode( this.moji ); document.body.appendChild( txt ); } } var a =new hoge(); a.moji="テスト"; a.view(); 【やってみたこと】 function hoge(){ this.view = function(){ var _this = this; var func = function(){ _this.foo()}; this.addListener( 'window', 'load', func ); } this.addListener = function(elem,type,func){ elem.addEventListener( type,func, false ); } this.foo =function(){ var txt = document.createTextNode( this.moji ); document.body.appendChild( txt ); } } var a =new hoge(); a.moji="テスト"; a.view();

  • HTML id名とjavascript変数名

    <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <title>test</title> <script type="text/javascript"> window.onload = function() { console.log('test' in window); test.addEventListener('click', function() { alert('click') }, false); }; </script> </head> <body> <div id="test">test</div> </body> </html> 何かすごい勘違いをしていたらお恥ずかしいのですが、 上のコードFIREFOX以外(IE、Chrome、safari)'true'でtestをクリックするとalertが 出るのですが、これって自動的にid名がグローバル変数になってるって ことなのでしょうか?? id名と同じ名前で変数を宣言していて、ぶち当たりました。 どうぞよろしくお願いいたします。

  • javascriptについて教えてください。

    divのボタンを作りたいと思い、調べながらjQueryを使う方法は以下のようにしたらいい事は分かったのですが、jQueryを使わずにしようと思い $(function(){ $("div").click(function(){ var x = this.id; alert(x); }); }); の部分を document.getElementsByTagName("div").onclick = function(){ var x = this.id;  alert(x); }; としてみたのですが、うまくいきません。jQueryを使わずに同じようなボタンを作るにはどうしたらいいのでしょうか? <!doctype html> <html> <head> <meta charset="UTF-8"> <title>無題ドキュメント</title> <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.4.min.js"></script> <script type="text/javascript" language="javascript"> $(function(){ $("div").click(function(){ var x = this.id; alert(x); }); }); </script> </head> <body> <div id="aaa" class="div_link">a</div> <div id="bbb" class="div_link">b</div> <div id="ccc" class="div_link">c</div> <div id="ddd" class="div_link">d</div> <div id="eee" class="div_link">e</div> </body> </html>

  • javascriptの動的読み込みについて教えてください

    javascriptの動的読み込みについて教えてください いつもお世話になります。 jqueryを勉強中のものです。 少しややこしいのですが、 以下のmenu.htmlとmain.htmlを持ったframe.htmlで、メニューの試験ボタンを押してmain.htmlの<div id="target_id">にload.htmlを動的に読み込んだ時、loadされたhelloボタンが作動しません。 menu.htmlのtest()中のalert(data);でload.htmlの<script>が読み込まれていることは確認できるのですが・・何が原因でどこが悪いのでしょうか? よろしくご指導お願いします。 frame.html ----------------------------------------------------------- <html> <head> <title>Dynamic Load Test</title> </head> <frameset name="frame" cols="180,*"> <frame name="menu" src="menu.html"> <frame name="MainPanel" src="main.html"> </frameset> </html> ----------------------------------------------------------- menu.html ----------------------------------------------------------- <html> <head> <script src="http://code.jquery.com/jquery-latest.js"></script> <script type="text/javascript"><!-- function test(){ jQuery.get("./load.html",function(data){ alert(data); $("#target_id",window.parent.MainPanel.document).html(data); }); } // --></script> </head> <body> <button onClick="test();">試験</button> </body> </html> ----------------------------------------------------------- main.html ----------------------------------------------------------- <html> <head> </head> <body> <h1>main.html</h1> </body> <div id="target_id"></div> </html> ----------------------------------------------------------- load.html ----------------------------------------------------------- <h1>load.html</h1> <script type="text/javascript"><!-- function hello(){ alert("こんにちわ"); } // --></script> <button onClick="hello();">hello</button> -----------------------------------------------------------

  • Firefoxで入力値のチェック

    テキストボックスへの入力値を即時でチェックし、値が不正だった場合はそのテキストボックスから抜けれないようにしたいと考えています。 以下のコードはIE6、Opera8.5では動作しましたが、Firefox1.5ではalertとselectはされるものの、focusがされず、結果テキストボックスから抜けてしまいます。 Firefoxで上記のことをするにはどうしたらよいのでしょうか。 <html> <head> <script type="text/javascript"> function validate(e){ var t = document.getElementById("txt1"); if(t.value == "a"){ alert("だめ!!"); if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } t.select(); t.focus(); return false; } } function bodyOnLoad(){ var t = document.getElementById("txt1"); addListener(t, "change", validate, false); } function addListener(e, evtname, func, foo){ if(e.addEventListener){ e.addEventListener(evtname, func, foo); }else if(e.attachEvent){ e.attachEvent("on" + evtname, func); } } </script> </head> <body onload="bodyOnLoad();"> <input type="text" id="txt1"> <input type="text" id="txt2"> </body> </html>