DOM on-イベントハンドラ

ウェブプラットフォームでは、DOM イベントを通知するための方法をいくつか提供しています。よく使われる2つの方法は、一般化された addEventListener() と、具体的な on-イベントハンドラ一式です。このページでは、後者がどのように機能するのかの詳細について注目します。

on-イベントハンドラの登録

on-イベントハンドラは、その要素がどのようにイベントに反応するかを管理しやすくするための DOM 要素に提供された一覧のプロパティです。対話型要素 (リンク、ボタン、画像、フォームなど) にも非対話型要素 (ベース文書など) にもあります。イベントは、クリック、押されたキーの検出、フォーカスの取得などの行為です。 on-イベントハンドラは通常、onclickonkeypressonfocus など、反応するように設計されたイベントに従って名前が付けられます。

定められたオブジェクトの特定のイベント (click など) に対して on<...> イベントハンドラをさまざまな方法で指定することができます。

  • 要素に on{eventtype} という名前の HTML 属性を使用します。例:
    <button onclick="return handleClick(event);">,
  • または、JavaScript から対応するpropertyを設定します。例:
    document.getElementById("mybutton").onclick = function(event) { ... }.

各オブジェクトは、与えられたイベントに対して 1 つの on-イベントハンドラしか持てないことに注意してください (ただし、そのハンドラは複数のサブハンドラを呼び出すことができます)。同じイベントおよび/または同じ要素に対しですら、さまざまなイベントハンドラを互いに独立して適用したい場合はとくに、addEventListener() がイベントの通知を受け取るためのより良い方法であることが多いのはこのためです。

また、 on-イベントハンドラは、実際のハンドラ関数を割り当てることができるプレースホルダーとして機能するため、プログラマーの意思ではなく自動的に呼び出されることにも注意してください (ただし、 mybutton.onclick(myevent); のように使用することはできます)。

非要素オブジェクト

イベントハンドラはまた、 window, document, XMLHttpRequest などを含む、イベントを生成する多くの非要素オブジェクトのプロパティを使用して設定することもできます。次に例を示します。

xhr.onprogress = function() { ... }

詳細

on<...> 属性に対する HTML の値と対応する JavaScript プロパティ

on<...> 属性を介して登録されたハンドラは、対応する on<...> プロパティを介して利用できますが、その逆はできません:

<div id="a" onclick="alert('old')">Open the Developer Tools Console to see the output.</div>

<script>
window.onload = function () {
  var div = document.getElementById("a");
  console.log("Attribute reflected as a property: ", div.onclick.toString());
  // Prints: function onclick(event) { alert('old') }
  div.onclick = function() { alert('new') };
  console.log("Changed property to: ", div.onclick.toString());
  // Prints: function () { alert('new') }
  console.log("Attribute value is unchanged: ", div.getAttribute("onclick"));
  // Prints: alert('old')
}
</script>

歴史的な理由から、<body> および <frameset> 要素の一部の属性/プロパティは、実際にはその親 Window オブジェクトにイベントハンドラを設定します。(HTML 仕様はこれらを onblur, onerror, onfocus, onload, onscroll と命名しています。)

イベントハンドラのパラメータ、this バインディング、および返値

イベントハンドラが HTML 属性として指定されている場合、指定されたコードは次のパラメーターを持つ関数にラップされます:

  • event - {domxref("GlobalEventHandlers.onerror", "onerror")}} を除くすべてのイベントハンドラ。
  • onerror イベントハンドラの event, source, lineno, colno および errorevent パラメーターには、実際にはエラーメッセージが文字列として含まれています。

イベントハンドラが呼び出されると、ハンドラ内の this キーワードは、ハンドラが登録されている DOM 要素に設定されます。詳しくは、this キーワードの資料を参照してください。

ハンドラからの戻り値は、イベントが取り消されるかどうかを決定します。戻り値の具体的な処理はイベントの種類によって異なります。詳細については、HTML 仕様の「イベントハンドラ処理アルゴリズム」を参照してください。

イベントハンドラが呼び出されたとき

作成中 (非捕獲リスナー)

用語集

イベントハンドラという用語は、次のように使用されます。

  • イベントの通知を受けるように登録されている関数またはオブジェクト
  • または、より具体的には、<button onclick="alert(this)">window.onload = function() { /* ... */ }など、HTML の on... 属性または Web API のプロパティを介してイベントリスナーを登録するメカニズム。

イベントをリッスンするためのさまざまな方法を議論するときは、

  • イベントリスナーは、EventTarget.addEventListener() によって登録された関数またはオブジェクトを参照します。
  • 一方、イベントハンドラon... 属性またはプロパティを介して登録された関数を指します。

仕様書

仕様書 状態 備考
HTML Living Standard
event handlers の定義
現行の標準
HTML5
event handlers の定義
勧告

ブラウザーの互換性

Firefox 9 におけるイベントハンドラの変更

In order to better match the specifications, and improve cross-browser compatibility, the way event handlers were implemented at a fundamental level changed in Gecko 9.0 (Firefox 9.0 / Thunderbird 9.0 / SeaMonkey 2.6).

Specifically, in the past, event handlers were not correctly implemented as standard IDL attributes. In Gecko 9.0, this was changed. Because of this, certain behaviors of event handlers in Gecko have changed. In particular, they now behave in all the ways standard IDL attributes behave. In most cases, this shouldn't affect web or add-on content at all; however, there are a few specific things to watch out for.

イベントハンドラプロパティが存在することの検出

You can now detect the presence of an event handler property (that is, for example, onload), using the JavaScript in operator. For example:

if ("onsomenewfeature" in window) {
  /* do something amazing */
}

イベントハンドラとプロトタイプ

You can't set or access the values of any IDL-defined attributes on DOM prototype objects; that means you can't, for example, change Window.prototype.onload anymore. In the past, event handlers (onload, etc.) weren't implemented as IDL attributes in Gecko, so you were able to do this for those. Now you can't. This improves compatibility.