함수A의 제어권을 함수B에 넘겨주고
호출의 주체인 B가 A를 적절한 시점에 호출하는 형태에서
함수A를 콜백함수라고 한다.
var count = 0;
var cbFunc = function(){
console.log(count);
if(++count > 4) clearinterval(timer);
};
var timer = setInterval(cbFunc,300);
// -- 실행결과 --
// 0 (0.3초)
// 1 (0.6초)
// 2 (0.9초)
// 3 (1.2초)
// 4 (1.5초)
위의 경우에는 cbFunc
의 제어권을 넘겨받은 setInterval
의 판단하에
적절한 시점(0.3초마다)에 함수를 실행했다.
즉 제어권을 넘겨받은 함수가 콜백함수의 호출 시점에 대한 제어권을 가진다.
간단한 예로 map
메서드를 통해서 알아보자면,
var newArr = [10,20,30].map((currentValue,index)=>{
console.log(currentValue,index);
return currentValue + 5;
});
console.log(newArr);
// -- 실행결과 --
// 10 0
// 20 1
// 30 2
// [15, 25, 35]
var newArr2 = [11,21,31].map((index,currentValue)=>{
console.log(currentValue,index);
return currentValue + 5;
});
console.log(newArr2);
// -- 실행결과 --
// 0 11
// 1 21
// 2 31
// [5, 6, 7]
실행 결과를 보면 인자의 이름은 아무 상관 없이
위처럼 콜백함수를 넘겨받은 , 즉 제어권을 넘겨받은 코드에서
콜백함수의 인자에 어떤값을 어떤순서로 넘길지에 대한 제어권이 있다.
콜백함수의 This
는 간단하다.
콜백함수의 제어권을 가지는 함수의 this
를 this
로 가진다.
어떤 객체의 메서드로 있던 함수가 인자로 전달될 경우에는 객체의 메서드가 아닌 함수자체로 전달된다
제어권을 가지는 함수가 this
를 지정하지 않으면 원래대로 전역 객체를 this
로 가진다.
콜백함수에 어떤 객체의 메서드를 할당하더라도
그 메서드는 메서드가 아닌 함수로서 호출된다.
var obj = {
vars:[1,2,3],
logValues: function(v,i){
console.log(this.v.i);
}
};
obj.logValues(1,2); // {val:[1,2,3], logValues: f} 1 2
[4,5,6].forEach(obj.logValues); // Window {...} 4 0
어떤 함수에서 콜백함수 A를 사용한다.
콜백 함수 A 는 콜백함수 B를 사용한다.
콜백함수 B는 콜백함수 C를 사용한다
.
.
.
코드가 이런 형태로 들여쓰기 수준이 감당하기 어려울 정도로 깊어지면 콜백 지옥에 빠졌다고 한다.
이런 경우는 이벤트처리, 서버통신과 같이 비동기적인 작업을 위해 등장한다.
위와 같이 async await
을 이용하여 동기적으로 표현하는 방법도 있다.