콜백함수: 함수 혹은 메서드의 인자로 넘겨주는 함수
콜백함수는 다른 함수에게 인자와 함께 제어권도 넘긴다.
제어권을 받은 코드는 콜백 함수에 대한 제어권을 가진다.
setInterval
)콜백 함수도 함수라서 콜백 함수로 메서드를 전달하면 메서드가 아닌 함수로서 호출된다.
var obj = {
vals: [1,2,3],
logValues: function(v,i) {
console.log(this, v, i);
}
};
obj.logValues(1,2); // {vals:[1,2,3], logValues: f} 1 2
[4,5,6].forEach(obj.logValues); // Window {...} 4 0
// Window {...} 5 1
// Window {...} 6 2
인자로 this를 받는 함수가 아니라면 this 제어권이 없어서 this 값을 변경할 수 없다.
하지만 그럼에도 this를 지정할 수 있는 방법들이 있다.
//this를 변수에 담은 경우
var obj1 = {
name: 'obj1',
func: function(){
var self = this;
return function () {
console.log(self.name);
}
}
};
var callback = obj1.func();
setTimeout(callback,1000);
...
func메서드 내부에서 self변수에 this를 할당한다. 그럼 함수 호출 시 ‘obj1’이 반환된다.
이 방법은 this를 실제로 사용하지 않고 번거롭다. this를 사용하지 않는 방법은 아래와 같다.
//this사용 X
var obj1 = {
name: 'obj1',
func: function(){
console.log(obj1.name);
}
};
바라볼 객체를 지정했기 때문에 다른 객체를 바라보게 할 수 없어 this를 이용한 재활용이 불가능하다.
this를 변수에 담은 경우엔 재활용이 가능하다. “this를 변수에 담은 코드”에 이어서 작성해보겠다.
//함수 재활용
...
var obj2 = {
name:"obj2",
func: obj1.func
};
var callback2 = obj2.func();
setTimeout(callback2,1500); // 'obj2'
var obj3 = {name: 'obj3'};
var callback3 = obj1.func.call(obj3);
setTimeout(callback3, 2000); // 'obj3'
obj2
의 func
프로퍼티에 obj1.func
을 복사해 넣고 이를 callback2
에 담았다.obj1.func
함수를 실행하며 this
를 obj3
로 지정하여 callback3
에 담았다.재활용이 필요없다면 this를 사용하지 않아도 되며 상황에 따라 선택하면 될 것 같다.
self변수 보다는 bind메서드를 이용하는 것이 좋다.
var obj1 = {
name: 'obj1',
func: function(){
console.log(this.name);
}
};
setTimeout(obj1.func.bind(obj1),1000);
var obj2 = {
name:"obj2"
};
setTimeout(obj1.func.bind(obj2),2000);
콜백 지옥: 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드가 깊어지는 현상
주로 이벤트 처리, 서버 통신 등 비동기적 작업 시 발생한다.
동기: 요청과 그 결과가 동시에 발생, 요청한 자리에서 결과가 나온다.
비동기: 요청 응답을 즉시 처리하지 않아도, 대기 시간동안 다른 요청을 처리할 수 있다.
setTimeout
)addEventListener
)XMLHttpRequest
)비동기를 제어하기 위해 콜백 함수를 사용한다면 콜백 지옥에 빠질 수 있다.
아래의 방법들로 콜백 함수에서 벗어날 수 있다.