イベントリスナーでDOMで文字を表示する方法

このQ&Aのポイント
  • イベントリスナーを使用してDOMで文字を表示する方法について質問です。
  • イベントリスナーで読み込んだ後に、DOMを使用して文字を表示させたいのですが、「undefined」と表示される問題が発生しています。
  • この問題の解決策を教えてください。
回答を見る
  • ベストアンサー

イベントリスナーで読み込んだ後に、DOMで文字を表

イベントリスナーで読み込んだ後に、DOMで文字を表示させたい。 DOMを使って、文字を表示させるならイベントリスナーで読み込み必要があると思いました。 そこで、下記のように書いて試してみました。 function hoge(){ this.view = function(){ window.addEventListener( 'load',this.foo, false ); } this.foo =function(){ var txt = document.createTextNode( this.moji ); document.body.appendChild( txt ); } } var a =new hoge(); a.moji="テスト"; a.view(); すると、「undefined」と表示されます。 どうすればいいのでしょうか。よろしくお願いします。

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

  • ベストアンサー
  • Ogre7077
  • ベストアンサー率65% (170/258)
回答No.2

■ 追加の質問1の回答 addEventListener の第2引数に渡した関数は、 システムから実行される際に、引数としてオブジェクトを一つ渡されます オブジェクトの内容) http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event 使わないのであれば引数 event を省略しても言語仕様上は問題ありません。 ただ、この関数はリスナー用である、を暗示するために書いています。 ■ 追加の質問2の回答 addEventListener や onload などに指定するコールバック関数は、 一般的に呼び出し元を指定されずに実行されます。 そのため例示したクロージャー等を使った対策で「this を束縛する」のが一般的です。 ■ bind を使った対策 ECMA-262 5th の新機能である Function.prototype.bind を使います 最近になって追加された機能なので、古いブラウザでは使えません var bound = this.foo.bind(this); window.addEventListener( 'load', bound, false ); ■ EventListener インターフェース を使った対策 addEventListener の第2引数は、DOM仕様上は 「EventListener インタフェースを実装するオブジェクト」 でも大丈夫です。 参考) http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener ですので、ある特定のプロパティをhogeオブジェクトに追加(実装)し、 hogeオブジェクト自体を引数に渡せば、一般的なオブジェクト指向言語っぽくなります function hoge(){ this.handleEvent = function(){ this.foo() }; // 追加 this.view = function(){ window.addEventListener( 'load', this, false ) }; }

a-z_A-Z
質問者

お礼

詳しい説明をありがとうございます。 javascriptは、他の言語と比べて、thisのような独特の仕様のためいつも苦労します。 しかし、今回の回答のおかげで、「だいきらいなjavascript」から「きらいなjavascript」と、 私の中で少し昇格しました。 それでも、まだまだとっつきにくいところがたくさんあります。 これからも質問する機会が多々あると思いますが、その時はまたお願いします。 このたびは、本当にありがとうございました。 大変助かりました。

その他の回答 (1)

  • Ogre7077
  • ベストアンサー率65% (170/258)
回答No.1

クラス型オブジェクト指向言語では、 メソッド内の this は一般的に「メソッドが属するインスタンス」を表します。 ですが、クラスやメソッドが存在しない JavaScript では、 関数内の this は「関数の呼び出し元オブジェクト」を表します。 例: obj.関数 = function(){ 処理(this) }; obj.関数(); // obj が呼び出し元なので this == obj として実行される var 変数 = obj.関数; 変数(); // 呼び出し元がないので this == ? 変数.apply(obj); // むりやり明示したので this == obj addEventListener の第二引数に指定する値は関数オブジェクトなのですが、 この関数オブジェクトは呼び出し元が明記されずに呼び出されるので、 関数内では this == ? となります。 (たぶんグローバルオブジェクトだとは思いますが) というわけで、 誤) window.addEventListener('load',this.foo, false); // foo 内では、this == ? 正) var that = this; // この時点での this を保存 var closure = function(event){ that.foo() }; // foo 内では、this == that window.addEventListener('load', closure, false); // closure 内では、this == ? 他にも bind や handleEvent を使った解決方法も有ります

a-z_A-Z
質問者

お礼

ありがとございます。 希望通り表示されました。 しかし、まだよくわかっていません。 そこで質問が2つあります。 【質問1】 var closure = function(event){ that.foo() }; の、「event」は必要でしょうか? var closure = function(){ that.foo() }; ではダメでしょうか。 【質問2】 addEventListenerを使わず、alert(this.moji)のような場合は問題なく表示されました。 今回のような、「var that = this; 」をするのは、 addEventListener の第二引数が、呼び出し元が明記されずに呼び出されるからでしょうか。 【お願い】 参考のために、bind や handleEvent もおしえていただけないでしょうか。 よろしくお願いします。

関連するQ&A

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

    イベントリスナーの部分で、「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();

  • Ajaxによる非同期通信のイベントリスナ

    JavaScriptで以下の関数を実行した場合、(1)の実行後関数を抜けるので、 (2)のイベントリスナは(1)の実行後も呼ばれることはあるのでしょうか。    function hoge(){     var xhr = new XMLHttpRequest();     xhr.open("GET","http://www.example.com/data.txt");     xhr.onreadystatechange = function(){ //(2)      if(xhr.readyState == 4 && xhr.status == 200){       $("#foo").html(xhr.responseText);      }     }     xhr.send(null); //(1)    } ローカル変数xhrは、関数を抜けたら変数とその領域が解放されるので、 XMLHttpRequestインスタンスも消滅する、そして、インスタンスが 消滅してしまうと、onreadystatechangeプロパティも消滅すると思っ たためです。 (2)が(1)の実行後も呼ばれるとしたら、どのような仕組になっていると 理解すればよいのでしょうか。

  • 【DOM】HTMLのタグに対してはElementインターフェースが使えない?

    HTMLの「document」はXMLDocumentと完全に見立ててDOMを利用できないのでしょうか? <html>   <style>     .foo{       background: #999999;     }   </style>   <body>     <input class="foo" type="text" value="NNNN"/>   </body>   <script language=JavaScript type=text/javascript>   function hoge(){     var Nodes;     Nodes = document.getElementsByTagName("input");     alert(Nodes.item(0).nodeName)     alert(Nodes.item(0).getAttributeNode("class"))     alert(Nodes.item(0).hasAttributeNode("class"))   }   hoge();   </script> </html> 上記のようなコードを書いてもアラートに「foo」と表示されません。 また、hasAttributeNodeにおいては全く反応がありません。 DOMのElementインターフェースが使えないとすれば、 JavascriptからclassやonClickのイベントハンドラなど、 属性を動的に変更するにはどうすればいいでしょうか? 制限事項としてid属性やname属性は使用できません。 IE6での使用です。 以上、よろしくお願いします。

  • イベントリスナーがうまくいかない

    delBtnがない場合にイベントリスナーを読み込むとエラーが出てその後の処理が行われないため 下記のようにあった場合のみ予約するようにしたところ今度はクリックしても実行されない問題が起きました。 読み込み時は、エラーにならないようにし、かつボタンを押したときに要素を削除するようにするにはどうしたらよいでしょうか? var Result = document.getElementsByClassName('Result')[0].innerHTML = '<span class="u-mr-1rem">あああああ</span><input id="DelBtn" type="button" value="削除">; var Result = document.createElement('p'); BtnWrap.appendChild(Result); Result.classList.add('Result u-mtb-1rem'); var delBtn = document.getElementById('DelBtn'); if(delBtn !== null) { delBtn.addEventListener('click', function() { document.getElementsByClassName('Result')[0].remove(); }); }

  • Androidイベントリスナ、イベントハンドラ違い

    Androidににおける「イベントリスナ」「イベントハンドラ」の違いを教えてください ・イベントに対応するメソッドが、「View クラスのインターフェイス」「View クラス」に分かれている理由が分かりません ・なぜメソッドによって、「インターフェイス」にあったり、「クラス」にあったりするのでしょうか? ・「onKeyDown」みたいにAndroid 自体が自動検知(?)するイベント対応メソッドは、「View クラス」に書かれる決まり? ・「onClick」などのイベントは、リスナに登録しないと利用できないから(?)、「インターフェイス」に書いてある? ・「イベントリスナ」は、「イベントハンドラ」の一種類なのでしょうか? ▽6.5 UIイベントハンドリング - ソフトウェア技術ドキュメントを勝手に翻訳   https://sites.google.com/a/techdoctranslator.com/jp/android/guide/ui/ui-events#EventHandlers

    • ベストアンサー
    • Java
  • イベントハンドラに処理を追加するには?

    例えばbodyタグのonloadイベントハンドラに JavaScriptを使って処理を追加するにはどうすればよいのでしょうか? 例) ・rei.htm <html>  <script language="JavaScript" type="text/javascript">  function hoge(){   alert("hogeです");  }  function foo(){   alert("fooです");  }  </script>  <body onload="hoge();">  </body>  <script language="JavaScript" type="text/javascript">  document.body.onload += foo();  </script> <html> ※前提条件として、変更可能な箇所はscriptタグ内のみとなります。 「こんなんでいけないかな?」と思って上記のようにやってみたのですがうまくいきませんでした。 (結果はfoo()のみ実行され、hoge()は実行されませんでした。 alertでbody.onloadの中身を確認すると『function anonymous{hoge();}undefined』と表示されるので、なぜfoo()が実行されてhoge()が実行されないのかよくわかりませんが‥) また試しに document.body.onload += foo(); これを以下のように変更してみました。 document.body.onload = foo(); この時は、 ・foo()の実行  ↓ ・javascriptエラー  ↓ ・hoge()の実行 となりました。(これもなぜこうなるのかよくわかりせん) 以上、イベントハンドラに最初から任意に入れられている処理を残しつつ、 さらに処理を加えるにはどうすればよいのかご教示お願いします。

  • イベントリスナーに設定した関数内で、id属性の値を取得するには

    IEでイベントリスナーに設定した関数で、イベントを発生させた要素のid属性値を取得する方法が分からずに困っています。 記述したコードは下記のようになります。Firefoxではうまく動作しました。 clickHandler内でFirefoxのe.currentTarget.idに対応するような処理はどのように行えばよいでしょうか。 ------------ JavaScript部分 ----------------------- function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true; } else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r; } else { elm['on' + evType] = fn; } } function clickHandler(e) { var id; if (document.all && !window.opera) { // IEの場合に、ここの処理でid属性の属性地 hoge1やhoge2を取得したい。 // id = window.event.srcElement.id; これではだめ } else { id = e.currentTarget.id; } // idに応じた処理 } var elm1 = document.getElementById('hoge1'); var elm1 = document.getElementById('hoge2'); addEvent(elm1,'click',clickHandler,false); addEvent(elm2,'click',clickHandler,false); ------------ HTML部分 ----------------------- <li><a id="hoge1" href="#"><img src="●●" /></a></li> <li><a id="hoge2" href="#"><img src="●●" /></a></li> 先に進むことができずに困っています。よろしくお願いします。

  • 複数のイベントリスナーを設置するのは正しい?

    クリック時、マウスオーバー時、マウスアウト時の処理を作るとき、 イベントリスナーの使い方はこのようなやり方でよいでしょうか。 var d = document.getElement.ById("id"); d.addEventListener('click', function(e){ var tar=e.target; tar.style.backgroundColor ="#000000"; },false); d.addEventListener('mouseover', function(e){ var tar=e.target; tar.style.backgroundColor ="#aaaaaa"; },false); d.addEventListener('mouseout', function(e){ var tar=e.target; tar.style.backgroundColor ="#555555"; },false);

  • イベントリスナのコールバックメソッドは何故一つ?

    Android(JAVA)のイベントリスナについて教えてください >イベントリスナは、ひとつのコールバックメソッドを持つ View クラスのインターフェイスです。それらのメソッドは、リスナが登録されたビューでユーザがUI のアイテムにアクションを起こしたことがトリガとなり Android フレームワークにより呼び出されます ▽6.5 UIイベントハンドリング - ソフトウェア技術ドキュメントを勝手に翻訳   https://sites.google.com/a/techdoctranslator.com/jp/android/guide/ui/ui-events ・なぜ、コールバックメソッドをひとつしか持たないのでしょうか? ・複数持ってはいけないのでしょうか? ・インターフェイスだから? ・言語機能として複数保持出来ないことはないけれども、イベントリスナ的に分かりやすくするため(?)、敢えて機能毎に分けているのでしょうか? ■質問背景 ・ドキュメント見てたらそうなってたので、なんでかな? と思い質問しました ・複数インターフェイスにそれぞれ唯一の抽象メソッドを持たせず、1つのインターフェイスに複数の抽象メソッドを持たせたほうが分かりやすいような気もするのですが… 「View.AllListener」に「onClick()」「onLongClick()」みたいなのは何故ダメなのでしょうか?

    • ベストアンサー
    • Java
  • IEでDOMインターフェースを拡張したい

    IEでDOMインターフェースを拡張したい NodeList.prototype.hoge=function(){…} のように、メソッドやプロパティを拡張しようとしたところ、IEでつまづいてしまいました…。 上記のようなコードの場合、「NodeListは宣言されていない…」のようなエラーが表示されます。また、 var NodeList としてみたところ、今度は「'prototype'はNullまたはオブジェクトではありません」と表示されました。 そこで、各DOMインターフェースを alert(Document); alert(Element); … のようにして調べてみたところ、どれも[object]が返ってきました。(もちろんjavascriptコアインターフェースでは期待通りの値が返ってきました。) それで結局のところ、IEでDOMインターフェースを拡張するにはどうすればいいのでしょうか?よろしくお願いします。

専門家に質問してみよう