[javascript] 콜백함수를 임시변수에 인자를 담아 실행하는 경우

조회수 167회

안녕하세요. addEventListener에 콜백함수를 임시변수에 담아 호출하는 경우에 갑자기 궁금한것이 생겼습니다. 원래는 스크롤 이벤트가 발생했을때 콜백함수로 그 이벤트가 잘 넘어오는지 확인해주려고 코드를 우선 작성해봤는데요.

    var printEvent = function(e){
      console.log(e); 
    }
    window.addEventListener('scroll',printEvent));

생각해보니 printEvent 라는 함수는 원래 실행될때 e가 정의되어 있어야하고, 함수를 실행할때 printEvent 안에 인자를 넣어주어야 했습니다.

    var printEvent = function(e){
      console.log(e); 
    }
    printEvent(10);

직관적으로 콜백함수가 인자가 없는경우에는 임시변수의 이름만 넣어주어도 당연히 실행될것같은데요. 이렇게 콜백함수의 인자로 e를 받는경우에는 window.addEventListener('scroll',printEvent(e)); 이렇게 인자를 전달해 주어야하지 않나요?

그래서 그렇게 작성한 뒤 코드를 실행시켜보았습니다.

    var printEvent = function(e){
      console.log(e); 
    }
    window.addEventListener('scroll',printEvent(e));

e is not defined라고 나오더군요. 이 오류는 const e = 10; 이런식으로 정의 되지 않았기 때문에 발생하는 오류인데요.

질문 1) 인자를 받는 콜백함수는 임시변수로 콜백함수를 받아서 실행할때 임시변수만 입력해도 인자가 함께 넘어간것으로 취급하는 것인가요?

질문 2) addEventListener함수는 어쨌든 콜백함수가 e를 인자로 받기때문에.. 내부적으로 이벤트를 리턴해주거나, 이벤트가 선언이 되는것이지요?

질문 읽어주셔서 감사합니다!!

1 답변

  • 답변1. 아닙니다.

    답변2. 외부에서 이벤트시 실행할 action을 등록한다는 개념으로 접근하셔야 합니다. 내부적으로 이벤트가 발생하면 등록한 콜백을 실행하되, 그 함수의 인자로 (미리 스펙이 정의된) 이벤트 객체를 만들어서 넣어주는 것입니다.

    event 객체를 콜백에 넣어주는 주체가 누구인지 아는게 중요합니다.

    예를 하나 들어볼게요.

    // window.addEventHandler를 단순하게 에뮬레이션한 코드입니다.
    var obj = {
      typeDescription: ['foo', 'bar', 'baz'],
    
      addListener: function (type, handler) {
        // 타입이 명세에 있고,
        // handler가 실행 가능한 함수라면
        if (this.typeDescription.indexOf(type) >= 0 && typeof handler === 'function') {
          window.setTimeout(function() {
            var event = { type: type, timeStamp: Date.now() };
            handler(event); // 리스너가 받아온 핸들러를 특정 시점에 [실행]합니다.
          }, 100);
        }
      }
    };
    
    var printEventObject = function (e) {
      console.log(e);
    }; // 함수 표현 식입니다.
    
    obj.addListener('foo', printEventObject); // 여기서 [실행]시키지 않습니다.
    

    그럼 말씀한신 경우를 살펴보시죠.

    obj.addListener('foo', printEventObject(e)); 
    

    이 경우 2번째 인자인

    printEventObject(e)
    

    이 함수가 먼저 evaluation 됩니다. 그리고 e라는 값은 접근 가능한 스코프 내에 선언된 것이 없으므로 참조 에러를 뱉습니다.

    임시 변수를 쓰지 않는, 정상적으로 동작하는 코드와 비교해 보면,

    obj.addListener('foo', function(e) { //결국 같은 함수 표현 식(function expression) 입니다.
      console.log(e);
    }); 
    

    두 번째 인자를 보면 함수를 만들기만 했을 뿐 실행 시키지는 않았습니다.

    콜백이라 함은 실행 가능한 형태를 넘겨주는 것이지, 그 함수를 실행시킨 형태를 넣어주지는 않습니다.

    질문 상황과는 별개로,

    다음과 같은 함수 실행을 넘긴 형태(클로져)라도 외부에서 e 값을 받아서 넘기지는 않습니다.

    var printTimeStamp = function (prefix) {
      return function(e) { // "이벤트 객체 받아서 잘 쓸게요" 의 의미
        console.log(prefix + e.timeStamp);
      };
    };
    obj.addListener('foo', printTimeStamp('Time: ')); 
    

    하지만 정상동작하죠. printTimeStamp가 리턴하는 함수가 인자를 잘 받도록 설계되어 있기 때문입니다.

    임시 변수로 이벤트를 등록하는 시점에, 이벤트 값 e가 보이지 않아서 변수에 등록한 함수에 넘겨주려면 뭔가 해야되는거 아닌가 싶지만 그럴 필요가 없는 것입니다. 넘겨주는 핸들러만 요구하는 폼에 맞게 넘겨주면 됩니다.

답변을 하려면 로그인이 필요합니다.

Hashcode는 개발자들을 위한 무료 QnA 사이트입니다. 계정을 생성하셔야만 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)

ᕕ( ᐛ )ᕗ
로그인이 필요합니다

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 계정을 생성하셔야만 글을 작성하실 수 있습니다.