web-dev-qa-db-ja.com

パラメーター付きのJavaScriptイベントハンドラー

イベントといくつかのパラメーターを渡すeventHandlerを作成します。問題は、関数が要素を取得しないことです。以下に例を示します。

doClick = function(func){
    var elem = .. // the element where it is all about
    elem.onclick = function(e){
        func(e, elem);
    }
}
doClick(function(e, element){
    // do stuff with element and the event
});

「elem」は、匿名関数の外部で定義する必要があります。渡された要素を取得して匿名関数内で使用するにはどうすればよいですか?これを行う方法はありますか?

そして、addEventListenerはどうですか? addEventListenerを介してイベントを渡すことができないようです。

更新

「これ」で問題を修正したようです

doClick = function(func){
    var that = this;
    this.element.onclick = function(e){
        func(e, that);
    }
}

これに関数でアクセスできるthis.elementが含まれている場合。

addEventListener

しかし、私はaddEventListenerについて疑問に思っています:

function doClick(elem, func){
    element.addEventListener('click', func(event, elem), false);
}
70
sebas2day

あなたのコードが何をしようとしているのか正確にはわかりませんが、関数クロージャーの利点を使用して、イベントハンドラーで変数を使用可能にすることができます。

function addClickHandler(elem, arg1, arg2) {
    elem.addEventListener('click', function(e) {
        // in the event handler function here, you can directly refer
        // to arg1 and arg2 from the parent function arguments
    }, false);
}

正確なコーディング状況に応じて、ほとんどの場合、何らかのクロージャーを使用して変数へのアクセスを維持できます。

あなたのコメントから、あなたが達成しようとしているのがこれなら:

element.addEventListener('click', func(event, this.elements[i]))

次に、実行中にクロージャーで必要な引数をキャプチャし、実際のイベントハンドラー関数を返す自己実行関数(IIFE)でこれを行うことができます。

element.addEventListener('click', (function(passedInElement) {
    return function(e) {func(e, passedInElement); };
}) (this.elements[i]), false);

IIFEの機能の詳細については、他の参照資料をご覧ください。

匿名関数内のJavascriptラッピングコード

JavaScriptの即時呼び出し関数式(IIFE)-jQueryの受け渡し

匿名関数を自己実行するJavaScriptの良い使用例は何ですか?

この最後のバージョンは、おそらく次のように何をしているのか見やすくなります。

// return our event handler while capturing an argument in the closure
function handleEvent(passedInElement) {
    return function(e) {
        func(e, passedInElement); 
    };
}

element.addEventListener('click', handleEvent(this.elements[i]));

.bind() を使用して、コールバックに引数を追加することもできます。 .bind()に渡す引数は、コールバック自体が持つ引数の前に追加されます。だから、あなたはこれを行うことができます:

elem.addEventListener('click', function(a1, a2, e) {
    // inside the event handler, you have access to both your arguments
    // and the event object that the event handler passes
}.bind(elem, arg1, arg2));
77
jfriend00

これは古い質問ですが、よくある質問です。ここにこれを追加しましょう。

矢印関数の構文を使用すると、字句的にバインドされ、連鎖できるため、より簡潔な方法で実現できます。

矢印関数式は、this、arguments、super、またはnew.targetキーワードへの独自のバインディングはありませんが、通常の関数式の構文的にコンパクトな代替です。

const event_handler = (event, arg) => console.log(event, arg);
el.addEventListener('click', (event) => event_handler(event, 'An argument'));

イベントリスナーをクリーンアップする必要がある場合:

// Let's use use good old function sytax
function event_handler(event, arg) {
  console.log(event, arg);
}

// Assign the listener callback to a variable
var doClick = (event) => event_handler(event, 'An argument'); 

el.addEventListener('click', doClick);

// Do some work...

// Then later in the code, clean up
el.removeEventListener('click', doClick);

ここにクレイジーなワンライナーがあります:

// You can replace console.log with some other callback function
el.addEventListener('click', (event) => ((arg) => console.log(event, arg))('An argument'));

より従順なバージョン:健全な作業により適しています。

el.addEventListener('click', (event) => ((arg) => {
  console.log(event, arg);
})('An argument'));
15
SnnSnn

あなたが試すことができるのは、バインドメソッドを使用することです。これはあなたが求めていたものを達成すると思います。他に何もなければ、それはまだ非常に便利です。

function doClick(elem, func) {
  var diffElem = document.getElementById('some_element'); //could be the same or different element than the element in the doClick argument
  diffElem.addEventListener('click', func.bind(diffElem, elem))
}

function clickEvent(elem, evt) {
  console.log(this);
  console.log(elem); 
  // 'this' and elem can be the same thing if the first parameter 
  // of the bind method is the element the event is being attached to from the argument passed to doClick
  console.log(evt);
}

var elem = document.getElementById('elem_to_do_stuff_with');
doClick(elem, clickEvent);
9
Knight Yoshi

簡潔な答え:

x.addEventListener("click", function(e){myfunction(e, param1, param2)});

... 

function myfunction(e, param1, param1) {
    ... 
} 
2
user3093134

元の質問の更新を考えると、イベントハンドラーを渡す際にコンテキスト( "this")に問題があるようです。基本について説明します。こちら http://www.w3schools.com/js/js_function_invocation.asp

あなたの例の簡単な作業バージョンは次のように読むことができます

var doClick = function(event, additionalParameter){
    // do stuff with event and this being the triggering event and caller
}

element.addEventListener('click', function(event)
{
  var additionalParameter = ...;
  doClick.call(this, event, additionalParameter );
}, false);

Javascript call()&apply()vs bind()? も参照してください

2
Echsecutor

this内のdoThingsはウィンドウオブジェクトです。代わりにこれを試してください:

var doThings = function (element) {
    var eventHandler = function(ev, func){
        if (element[ev] == undefined) {
            return;
        }

        element[ev] = function(e){
            func(e, element);
        }
    };

    return {
        eventHandler: eventHandler
    };
};
0
jbabey