Javascript/core

callback 함수란?

student513 2020. 12. 19. 17:36

함수가 자신의 인자로 다른 함수를 받을 때, 인자로 넘겨진 함수를 callback 함수라고 한다.

callback함수는 자신을 인수로 받은 함수에게 제어권을 넘겨준다.

 

제어권에는 세 가지가 있다.

  1. 실행시점에 관한 제어권: 어떤 시점에 콜백함수를 호출할지
  2. 인자에 대한 제어권: 인자에는 어떤 값들을 넘겨줄지
  3. this에 대한 제어권: this에 무엇을 바인딩할지

실행시점에 대한 제어권

실행시점을 제어하는 것으로 흔히 예를 들 수 있는 함수는 setIntervalsetTimeout이 있다.

MDN의 setTimeout의 표준 사용법을 보자.

window.setTimeout(func[, delay, param1, param2, ...]);

[ ] 대괄호 안의 인자는 넣어도 되고 안 넣어도 되는 인자들이다.

맨 앞부분에는 func이 보인다. 이 부분에 callback함수가 인자로 넘겨진다.

setTimeout의 기능은 인자로 넘겨진 callback함수를 setTimeout 함수가 호출된 시점으로부터 delay ms 후에 호출하는 것이다.

 

사용법은 다음과 같다.

let timeoutID;

function delayedAlert() {
  timeoutID = window.setTimeout(slowAlert, 2000);
}

function slowAlert() {
  alert("That was really slow!");
}

delayedAlert();

setTimeout에 넘겨진 slowAlert가 2000ms(2초) 후에 실행된다.


인자에 대한 제어권

forEach라는 함수는 인자로 받은 callback함수에 넘어가는 인자를 결정한다.

arr.forEach(callback(currentvalue[, index[, array]])[, thisArg])

arr라는 배열의 메소드로 사용이 가능하다.

forEach의 기능은 다음과 같다.

 

"주어진 함수를 배열 요소 각각에 대해 실행합니다."

 

arr의 요소 각각에 대해 callback함수를 실행시켜주면 된다.

괄호가 중첩되어있어 복잡하지만 차근 차근 살펴보자.

 

callback(currentvalue[, index[, array]]): 콜백함수는 3개의 인자가 필요하다.

  • currentvalue: callback 함수로 실행시켜줘야할 배열의 요소 하나
  • index: 그 배열의 요소의 인덱스
  • array: forEach()를 호출한 배열

위 세 인자 모두 forEach를 호출한 arr로부터 파생되는 것이므로, callback함수의 인자에 대한 제어권은 forEach가 갖고 있다.


this에 대한 제어권

callback함수가 바인딩할 타겟을 임의로 설정하는 것이다.

대표적인 예로 addEventListener는 callback 함수가 바인딩할 타켓을 html element로 설정한다.

target.addEventListener(type, listener[, options]);

listener 자리에 callback함수가 들어오게 된다.

document.body.innerHTML = '<div id="a">abc</div>';

function cbFunc(x) {
    console.log(this);
}

document.getElementById('a').addEventListener('click', cbFunc);
//출력: <div id="a">abc</div> 

다음 코드에서 cbFunc는 <div id="a">abc</div>를 바인딩 타겟으로 설정하게 된다.


주의: 콜백은 함수지, 메소드가 아니다!

var arr = [1,2,3,4,5];
var obj = {
    vals: [1,2,3],
    logValues: function(v, i) {
        if(this.vals) {
            console.log(this.vals, v, i);
        } else {
            console.log(this, v, i);
        }
    }
};

메소드로 호출할 경우, 

obj.logValues(1, 2) // 출력: [1,2,3],1,2

callback함수로 넘겨줄 경우,

arr.forEach(obj.logValues)

logValues라는 메소드는 떨어져 나가고 function(v, i) { ... }만 forEach의 인자로 넘어가게 된다.

메소드가 가리키는 함수가 호출된 것이 아닌 인자로 넘어가기만 한 상황이다.

function의 바인딩 타겟은 window이기 때문에 다음과 같은 출력이 발생한다.

다음과 같은 출력이 발생한다.

출처: Javascript 핵심 개념 알아보기 - JS Flow, 정재남 강사님, 코어자바스크립트