JavaScriptアプリケーションで頭を悩ませる問題に遭遇しました。
このような要素を書くと:
<li onClick="alert(this.tagName)"></li>
「LI」が表示されます。
ただし、これを行うと:
<li onClick="foo()"></li>
「foo()」は次のとおりです。
function foo(){ alert(this.tagName); }
「未定義」になります。
アタッチされた関数に関して「これ」がどのように機能することになっているのか私は離れています。しかし、「これ」は要素を拾っていないため、デフォルトでは「ウィンドウ」にデフォルト設定されているため、困惑しています。なぜこれが起こっているのか理解できません。
誰か説明がありますか?
これは、JavaScript関数呼び出しでthisへの参照を渡していないためです。 JavaScript関数のthisはonClickの例と同じオブジェクトを参照しません。代わりにこれを試してください:
<li onClick="foo(this)"></li>
function foo(item){ alert(item.tagName); }
インラインリスナーで:
> <li onClick="alert(this.tagName)"></li>
Onclick属性値は効果的に関数にラップされ、これに設定された要素で呼び出されます。
function anon() {
/* attribute value */
}
anon.call(element);
本体に関数を置くと、基本的に次のようになります。
function anon() {
foo();
}
ここでは、this
内のanon
が要素になりますが、foo
はthis
を設定せずに呼び出されるため、未定義になります。非厳密モードでは、this
はデフォルトでグローバルオブジェクト(ブラウザではwindow
)になります。厳密モードでは、this
内のfoo
は未定義になります。
1つの解決策は、要素参照を関数に渡すことです。
<li onclick="foo(this)" ... >
次に関数で:
function foo(callingElement) {
...
}
あるいは:
<li onclick="foo.call(this)" ... >
function foo() {
var callingElement = this;
}
他の回答ですでに述べたように、this
の値は、それを含む関数の呼び出し方法によって異なります。しかし、あなたの例はイベントハンドラーに関するものなので、コメントでcjc343が言ったことを強調したいと思います。
インラインイベントハンドラーを削除すると、よりわかりやすくなる場合があります。
実際、それは非常に簡単です。このHTMLを考えると:
<ul id="list">
<li id="item1">item 1</li>
<li id="item2">item 2</li>
<li id="item3">item 3</li>
</ul>
次のJavaScriptは、インラインハンドラーの削除と委任の使用の両方を考慮します。
var list = document.getElementById('list');
list.addEventListener('click', function(evt){
console.log("this is the element the event is bound to: " + this.id);
console.log("the event target is the clicked element: " + evt.target.id);
});
これは、IE9を含むW3Cイベントモデルに準拠するすべてのブラウザーで機能します。古いIEでは、attachEvent
の代わりにaddEventListener
を使用し、イベント名の前に"on"
を追加する必要があります。詳細 こちら 。
thisをパラメーターとして渡す必要がない別のオプションは、 call または 適用 。これは、関数内でthisの値を設定するための組み込みメカニズムです。指摘しておきますが、HTMLに直接イベントハンドラーを追加するのは少し時代遅れです。イベントの委任についてJSフレームワークをチェックアウトすることをお勧めします( jQuery 、 Prototype 、 Dojo 、 [〜#〜] yui [〜#〜] など)。
フィドル: http://jsfiddle.net/bboone/Q2CkV/2/
[〜#〜] html [〜#〜]
<div onClick='alert(this.tagName);'>test</div>
<div onClick='foo.call(this);'>test2</div>
[〜#〜] js [〜#〜]
function foo(){ alert(this.tagName); }