콜백 함수 개요
콜백 함수는 다른 함수 또는 메서드에게 인자로 넘겨주면서 제어권도 함께 위임한 함수를 의미합니다. 일반적으로 다른 함수의 작업이 끝나면 실행되는 함수이며, 비동기나 복잡한 작업 환경에서 유용하게 사용됩니다.
콜백 함수 예제 - 제어권
let count = 0;
let timer = function() {
console.log(count);
if (++count > 5) clearInterval(alarm);
};
let alarm = setInterval(timer, 1000);
delay의 값을 입력받아 5번 울리면 alarm을 종료하는 timer 콜백함수를 만들고, setInterval에 timer와 delay를 넘겨주는 코드입니다.
timer()와 setInterval(timer, 10000) 코드를 호출 주체와 제어권으로 나누어 보자면 다음 표와 같습니다. 이처럼 콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수 호출 시점에 대한 제어권을 가지게 됩니다.
setInterval 메서드는 Window 또는 Worker 인스턴스에서 제공하는 메서드로 브라우저 환경에서 함수처럼 사용할 수 있습니다.
setIntervlal은 함수와 delay (ms 단위)를 인수로 받아 intervalID 값을 반환하며, clearInterval 메서드를 통해 ID값을 비교하여 실행을 종료합니다.
콜백 함수 - 인자
let array = [10, 20, 30].map(function(currentValue, index){
console.log(currentValue, index);
return currentValue + 5;
});
console.log(array);
// 실행 결과
// 10 0
// 20 1
// 30 2
// [15, 25, 35]
map 메서드를 사용하면 다음과 같이 모든 원소를 탐색하며 값, 인덱스 정보를 추출하여 콜백 함수를 반복 호출하고, 함수의 실행 결과를 통해 새로운 배열을 만들 수 있습니다.
Array.prototype.map(callback[, thisArg])
callback: function(currentValue, index, array)
Array의 prototype에 담긴 map 메서드는 다음과 같이 첫 번째 인자로 callback 함수를 받고, 생략 가능한 두 번째 인자로 콜백 함수 내부에서 this로 인식할 대상을 특정할 수 있습니다.
콜백 함수에 this 바인딩하기
콜백 함수는 어떤 객체의 메서드를 전달하더라도 메서드가 아닌 함수로 호출됩니다.
메서드를 콜백 함수로 전달하는 경우
let obj = {
vals: [1, 2, 3],
logValues: function(v, i) {
console.log(this, v, i);
}
};
obj.logValues(1,2);
[4, 5, 6].forEach(obj.logValues); // this : Window
메서드를 콜백함수로 전달한 경우, obj 객체와 직접 연관이 없어지며, forEach에 의해 콜백이 함수로서 호출되고 별도의 this 바인딩이 없기 때문에 this는 전역객체를 바라보게 됩니다.
this 바인딩 하는 방법
let obj1 = {
name: 'obj1',
func: function() {
let self = this;
return function() {
console.log(self.name);
};
}
};
let callback = obj1.func();
setTimeout(callback, 1000);
메서드 내부에서 this (obj1)를 저장하는 변수를 만들면 콜백 함수에서 호출할 때 obj1이 this로 바인딩된 상태로 콜백 함수를 호출할 수 있습니다.
let obj1 = {
name: 'obj1',
func: function() {
console.log(this.name);
}
};
setTimeout(obj1.func.bind(obj1), 1000);
let obj2 = {
name: 'obj2'
};
setTimeout(obj1.func.bind(obj2), 1500);
ES5부터 등장한 bind 메서드를 사용하면, this가 어떤 객체를 바라볼지 명시적으로 지정할 수 있습니다.
비동기 제어를 위해 콜백 함수를 사용하다 보면 콜백 지옥에 빠지기 쉽습니다.
자바스크립트 진영에서는 비동기적인 작업을 동기적으로, 또는 동기적으로 보여지게끔 처리해주는 기능을 구현하고자
ES6에는 Promise, Generator 등이 도입됐고, ES2017에는 async, await이 도입 되었습니다.
REFERENCE