アプリ版:「スタンプのみでお礼する」機能のリリースについて

イベントリスナーで読み込んだ後に、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」と表示されます。
どうすればいいのでしょうか。よろしくお願いします。

A 回答 (2件)

クラス型オブジェクト指向言語では、


メソッド内の 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 を使った解決方法も有ります
    • good
    • 0
この回答へのお礼

ありがとございます。
希望通り表示されました。

しかし、まだよくわかっていません。
そこで質問が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 もおしえていただけないでしょうか。
よろしくお願いします。

お礼日時:2014/04/17 00:36

■ 追加の質問1の回答



addEventListener の第2引数に渡した関数は、
システムから実行される際に、引数としてオブジェクトを一つ渡されます
オブジェクトの内容) http://www.w3.org/TR/DOM-Level-2-Events/events.h …

使わないのであれば引数 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.h …

ですので、ある特定のプロパティをhogeオブジェクトに追加(実装)し、
hogeオブジェクト自体を引数に渡せば、一般的なオブジェクト指向言語っぽくなります

function hoge(){
this.handleEvent = function(){ this.foo() }; // 追加
this.view = function(){ window.addEventListener( 'load', this, false ) };
}
    • good
    • 0
この回答へのお礼

詳しい説明をありがとうございます。

javascriptは、他の言語と比べて、thisのような独特の仕様のためいつも苦労します。
しかし、今回の回答のおかげで、「だいきらいなjavascript」から「きらいなjavascript」と、
私の中で少し昇格しました。

それでも、まだまだとっつきにくいところがたくさんあります。
これからも質問する機会が多々あると思いますが、その時はまたお願いします。

このたびは、本当にありがとうございました。
大変助かりました。

お礼日時:2014/04/18 00:31

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!