JavaScriptのインラインイベントハンドラーに引数としてイベントを渡す方法は?


103
// this e works
document.getElementById("p").oncontextmenu = function(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
};

// this e is undefined
function doSomething(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}
<p id="p" onclick="doSomething(e)">
    <a href="#">foo</a>
    <span>bar</span>
</p>

同様の質問がいくつかあります。

しかし、私のコードでは、またはなどのクリックされた子要素を取得しようとしていますaspan

ではevent、引数としてイベントハンドラーに渡す正しい方法は何ですか?または引数を渡さずにハンドラー内でイベントを取得する方法は?

編集する

私は承知しているaddEventListenerjQuery、にイベントを渡すためのソリューションを提供してくださいinlineイベントハンドラを。



5
addEventListenerに切り替えるのではなく、インラインイベントハンドラーを使用する十分な理由はありますか?en.wikipedia.org/wiki/Unobtrusive_JavaScript
Xotic750

2
@ Xotic750私にとっては、はい。たとえば、ajaxを介してHTMLを動的にロードまたは再ロードするときに、毎回手動で再バインドする必要はありません。
Wadih M.

回答:


166

eventオブジェクトを渡すには:

<p id="p" onclick="doSomething(event)">

クリックされた子を取得するにはelementeventパラメーターと一緒に使用する必要があります:

function doSomething(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}

element自身を渡すには(DOMElement):

<p id="p" onclick="doThing(this)">

jsFiddleのライブ例を見る


11
(そして疑問に思う方のために:はい、一部の[Firefoxなど]にグローバルeventオブジェクトがない場合でも、これはChrome、Firefoxなどで機能します。これは、DOM0ハンドラーが呼び出されるコンテキストにeventオブジェクトがあるためです(一部のブラウザでは)グローバルではありません。)
TJ Crowder 2013年

this意味しp、私は取得しようとしているaspan
user1643156

3
サポートされている限り、「イベント」を渡すことが私が知る唯一の方法です。この状況では「this」の解析は役に立ちません
Xotic750

5
@ user1643156それは非常に重要です。パラメータの名前は「イベント」と正確に同じでなければなりません
The-null-Pointer-

1
Wadih M.の答えはこれよりはるかに優れています。これは誤解を招く(他の同様の)ように、人々は "(event)"パラメータが関数呼び出しに入れられるべきだと人々に信じ込ませています。そのため、宣言する必要はありません(変数名は実際には渡されなかったため、変数名を変更しても違いがないことに気づくまでに数日かかりました)。また、そこに与えられた説明は、JSがなぜそのように機能するのかについての疑念を却下します(たぶん、そうすべきではありませんが、それは私が判断することではありません...)
Cyber​​knight

15

インラインイベントは関数として実行されるため、引数を使用するだけで済みます

<p id="p" onclick="doSomething.apply(this, arguments)">

そして

function doSomething(e) {
  if (!e) e = window.event;
  // 'e' is the event.
  // 'this' is the P element
}

受け入れられた回答に記載されている「イベント」は、実際には関数に渡される引数の名前です。グローバルイベントとは何の関係もありません。


良いヒント。ときに人々は、Webコンポーネントの採用が開始されますcall()apply()、主流jsのフレームワークで利用可能な機能をデータバインディングをエミュレートするに不可欠なことを証明します。もう1つのトリックはObject.assign(this.querySelector('my-btn'), this)、Webコンポーネントの内部と同様のことを行うことです。インラインイベントから親Webコンポーネントクラスの任意のメソッドにアクセスできますonclick="toggleBtnActive.call(this, true)"
エイドリアンモイサ

8

を渡す必要はありません。デフォルトで自動的に渡されthiseventオブジェクトが既に存在し、そこには元のオブジェクトが含まevent.targetれています。構文を軽くすることができます:

この:

<p onclick="doSomething()">

これで動作します:

function doSomething(){
  console.log(event);
  console.log(event.target);
}

eventオブジェクトをインスタンス化する必要はありません。すでに存在しています。やってみよう。そしてevent.target、これを呼び出すオブジェクト全体が含まれます。これは、以前「this」として参照していました。

コードのどこかから動的にdoSomething()をトリガーすると、それeventが未定義であることがわかります。これは、クリックのイベントからトリガーされなかったためです。したがって、イベントを人為的にトリガーしたい場合は、次のように使用しますdispatchEvent

document.getElementById('element').dispatchEvent(new CustomEvent("click", {'bubbles': true}));

その後、いつものようにdoSomething()見ていきます!eventevent.target

thisどこにでも渡す必要はありません。関数のシグネチャを配線情報から解放し、物事を簡素化できます。


少なくともIE11では、これは当てはまりません。デフォルトの引数はありません。
cskwg

1
@cskwg IE11でも動作します。これは下位互換性のために必要であるため、すべての主要ブラウザで動作します。回答で述べたように、イベントが存在する唯一のシナリオであるイベントからJavaScript関数が呼び出された場合にのみ、「イベント」と呼ばれるオブジェクトがすでに存在し、関数内で簡単にアクセスできます。関数プロトタイプに追加の配線を渡します。IE11を搭載したマシンでonclickイベントのテストを行ったところ、「event」変数に「PointerEventオブジェクト」が含まれていました。
Wadih M.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.