매개 변수가있는 자바 스크립트 이벤트 핸들러


89

이벤트와 일부 매개 변수를 전달하는 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를 통해 이벤트를 전달할 수없는 것 같습니다.

최신 정보

나는 'this'로 문제를 해결하는 것 같았다

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);
}

2
질문에 관련된 요소, 요소, 요소가 있습니다. 덜 혼란 스러울 수 있습니까?
mihai

죄송합니다. 제 상황의 예를 만들려고했지만 잘되지 않아 코드를 업데이트했습니다.
sebas2day

e.target/를 찾고 e.currentTarget계십니까?
Rolf

1
이것을 사용하는 경우 매개 변수를 보내는 방법 : ok.addEventListener ( "click", this.changeText.bind (this));
Alberto Acuña

답변:


103

코드가 무엇을 하려는지 정확히 이해하지 못하지만 함수 클로저의 장점을 사용하여 모든 이벤트 처리기에서 변수를 사용할 수 있도록 만들 수 있습니다.

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의 IIFE (Immediately-Invoked Function Expression)-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));

예, 이것은 거의 내가하려는 일이지만 익명 함수가 addClickHandler에 의해 매개 변수로 전달 되고이 함수에 다음과 같은 이벤트와 함께 매개 변수를 제공하려면 어떻게해야합니까? element.addEventListener ( 'click', func (event, this.elements [i]));
sebas2day 2012

5
@ sebas2day-당신은 할 수 없습니다 element.addEventListener('click', func(event, this.elements[i])). Javascript는 그렇게 작동하지 않습니다. 클로저를 사용하는 다른 방법이 있지만 작성한 방식으로는 할 수 없습니다. addEventListener는 정확히 하나의 인수 (이벤트)를 사용하여 콜백을 호출하며 어떤 식 으로든 변경할 수 없습니다.
jfriend00

대답 끝에 이것을 수행하는 또 다른 예를 추가했습니다.
jfriend00

@ jfriend00 당신이 할 수있는 일은 bind 메소드를 사용하는 것입니다. function eventFunction (arg, evt) { console.log(arg[0],arg[1],arg[2]) console.log(evt) } var el = document.getElementById('elementID'); el.addEventListener('click', eventFunction.bind(el,[1,2,3])) 이벤트 인수는 항상 함수의 인수에서 마지막이며 bind 메서드에서 명시 적으로 선언되지 않습니다.
Knight Yoshi 2015 년

2
@ Bosh19-질문 한 구성을 설명하기 위해 내 답변 끝에 추가 한 내용을 참조하십시오. 즉시 실행되는 익명으로 선언 된 함수 인 IIFE (즉시 호출 된 함수 식)입니다. 함수를 정의한 다음 호출하는 바로 가기입니다. 본문을 인라인하고 싶을 때 유용하며 다른 곳에서는 호출되지 않으므로 이름이 필요하지 않습니다.
jfriend00 2015-04-14

28

오래된 질문이지만 일반적인 질문입니다. 여기에 이것을 추가하겠습니다.

화살표 함수 구문 을 사용하면 어휘 적으로 바인딩되고 연결될 수 있기 때문에보다 간결한 방법을 얻을 수 있습니다.

화살표 함수 표현식은 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'));

2
이것은 합리적인 해결책처럼 보이지만 동일한 이벤트 리스너를 제거해야 할 때 어떨까요?
Dushyant Sabharwal

@SnnSnn : +1. 이벤트 핸들러에 클래스 속성을 제공하기 위해 이것을 사용했습니다. 나는 방금 전달했고 this핸들러는 필요한 것에 액세스 할 수 있습니다.
Robotron

내 이해가 맞다면 실제로 익명 함수를 이벤트 핸들러로 전달하는 것입니다 : (e) => {....}이며 yourEventHandlerFunction ()이 아닙니다. 시작하는 익명 함수를 전달했기 때문에 나중에 이벤트 핸들러를 제거하려는 경우 문제가 발생합니다.
PowerAktar

답변은 이벤트 리스너를 제거하는 방법을 명확하게 설명하므로 문제가 없습니다.
snnsnn

9

시도해 볼 수있는 것은 bind 메서드를 사용하는 것입니다. 이것이 여러분이 요청한 것을 달성한다고 생각합니다. 다른 것이 없다면 여전히 매우 유용합니다.

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);

2

원래 질문에 대한 업데이트를 감안할 때 이벤트 핸들러를 전달하는 동안 컨텍스트 ( "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);

참조 ) (자바 스크립트 호출 () 바인드 대 () 적용을?


2

짧은 답변:

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

... 

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

이것은 올바르게 작동하지 않습니다. 이벤트 핸들러가 설정 될 때마다 매개 변수 값이 변경되면 param1또는 값을 초과하지 않기 때문에 예기치 않은 결과가 생성됩니다 param2. 이러한 값이 변경되면 이벤트 핸들러가 생성 된 당시의 값으로 설정되지 않습니다. 현재 값으로 만 설정됩니다. 또한 이것은 이벤트 리스너 함수의 범위 밖에서 변수를 설정하고 이벤트 핸들러에서 해당 변수를 참조하는 것과 다르지 않으므로 매개 변수 전달을 전혀 수행하지 않습니다.
TetraDev

나는 정말로 당신의 요점을 이해하지 못했기 때문에 내 응답이 꺼질 수 있습니다. 어쨌든 이벤트 핸들러는 한 번 설정됩니다 (항상 그런 것은 아니지만 일반적으로 누군가가 원하는 것입니다). 둘째, 이것은 핸들러 함수가 myfunction이고 2 개의 매개 변수와 "event"변수가 있음을 거의 나타냅니다. 셋째, 예, 작동하며 결과는 예상대로 정확합니다.
user3093134

아니요, 작동하지 않습니다. 나는 당신이했던 것과 똑같이 테스트했으며 내 요점은 유효합니다. 경우 param1이다 noodle에서 addEventListener가 처음 호출, 그리고 당신이 그것을 호출 할 두 번째 시간 param입니다 cheese이벤트 리스너 때마다 다음 click화재가 param1설정됩니다 cheese하지 noodle. 따라서 이벤트 리스너가 추가 될 때 존재했던 값을 기억하기 위해 "클로저"를 사용하지 않습니다. 내 포인트가 유효하기 위해 설명 할 필요가없는 이벤트 리스너를 여러 번 추가해야하는 시나리오가 있습니다.
TetraDev

저는 전문가가 아니고 프로그래밍에서 "폐쇄"에 대해 들어 본 적이 없어서 당신이 의미하는 바를 이해하지 못합니다.
user3093134

1
확인해 주셔서 감사합니다. 게시하신 링크도 꼭 방문하겠습니다. 또한, 나는 그것을 유지하고 좋은 일 :이, 당신은 매우 예의 바르고 정직 선생님입니다 '라고해야
user3093134

0

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
    };
};

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.