콜백함수 📖
다른 함수가 실행이 끝난 뒤 실행되는(=callback) 함수를 말합니다! 그리고 다른 함수로 인자를 넘겨주는 함수입니다!
즉, 콜백 함수는 다른 함수에 인자를 넘겨줌으로써 그 제어권도 함께 위임한 함수입니다. 콜백함수를 위임받은 코드는 자체적으로 내부 로직에 의해 콜백 함수를 적절한 시점에 실행하게 됩니다.
function func(callback) {
callback();
}
function callback() {
console.log("callback 함수입니다.");
}
func(callback);
// 결과 : callback 함수입니다.
❗간단하게 설명하면 함수를 등록하기만 하고 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 호출하는 함수!
제어권 📖
1. 호출 시점
콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수 호출 시점에 대한 `제어권`을 갖습니다.
아래 예시를 보시면 `setInterval`함수는 언제 콜백 함수를 호출할지에 대한 제어권을 가지게 돼서 0.3초 동안 출력되는 걸 볼 수 있습니다.
var count = 0;
var cbFunc = function () {
console.log(count);
if (++count > 4) clearInterval(timer);
};
var timer = setInterval(cbFunc, 300);
// 실행 결과
// 0 (0.3sec)
// 1 (0.6sec)
// 2 (0.9sec)
// 3 (1.2sec)
// 4 (1.5sec)
2. 인자
콜백 함수를 넘겨받은 map 메서드는 제어권을 가지고 있기 때문에 인자의 순서까지도 제어권이 있습니다!
아래 코드를 보시면 첫 번째 인자로 `index` 두 번째 인자로 `currentValue`로 설정해도 map 메서드의 규칙에 맞게 호출되는 걸 확인할 수 있습니다!
// map 함수에 의해 새로운 배열을 생성해서 newArr에 담고 있네요!
var newArr2 = [10, 20, 30].map(function (index, currentValue) {
console.log(index, currentValue);
return currentValue + 5;
});
console.log(newArr2);
// -- 실행 결과 --
// 10 0
// 20 1
// 30 2
// [ 5, 6, 7 ]
3. this
제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조합니다!
// Array.prototype.map을 직접 구현해봤어요!
Array.prototype.mapaaa = function (callback, thisArg) {
var mappedArr = [];
for (var i = 0; i < this.length; i++) {
// call의 첫 번째 인자는 thisArg가 존재하는 경우는 그 객체, 없으면 전역객체
// call의 두 번째 인자는 this가 배열일 것(호출의 주체가 배열)이므로,
// i번째 요소를 넣어서 인자로 전달
var mappedValue = callback.call(thisArg || global, this[i]);
mappedArr[i] = mappedValue;
}
return mappedArr;
};
const a = [1, 2, 3].mapaaa((item) => {
return item * 2;
});
console.log(a);
제어권을 넘겨받을 코드에서 call / apply 메서드의 첫 번째 인자에서 콜백 함수 내부에서 사용될 this를 명시적으로 바인딩 하기 때문에 this에 다른 값이 담길 수 있습니다!
call / apply 가 궁금하면❓
콜백 함수 내부에서의 this 📖
콜백 함수 내부의 this에 다른 값을 바인딩하는 방법
아래 코드는 내부에 `self`변수를 이용해 this를 저장해 obj1.name을 리턴하는 방식으로 사용하고 있습니다.
var obj1 = {
name: 'obj1',
func: function() {
var self = this; //이 부분!
return function () {
console.log(self.name);
};
}
};
var callback = obj1.func();
setTimeout(callback, 1000);
그러나 단순히 함수만 전달한 것이기 때문에 obj1 객체와는 상관이 없죠.
그렇다면 콜백 함수 내부에서 this를 사용하지 않는다면❓
var obj1 = {
name: 'obj1',
func: function () {
console.log(obj1.name);
}
};
setTimeout(obj1.func, 1000);
첫 번째 예제보다는 간결해졌지만 this를 하지 않아서 다양한 것을 할 수 있는 장점을 놓치고 있습니다.
그래서 this를 우회적으로 활용할 수 있는 방법에 대해서 알려드리겠습니다!
var obj1 = {
name: 'obj1',
func: function() {
var self = this; //이 부분!
return function () {
console.log(self.name);
};
}
};
// 역시, obj1의 func를 직접 아래에 대입해보면 조금 더 보기 쉽습니다!
var obj3 = { name: 'obj3' };
var callback3 = obj1.func.call(obj3);
setTimeout(callback3, 2000);
첫 번째로 call 메서드를 사용하게 되면 `obj1.func`의 함수를 즉시 실행하고 `obj3`에 this를 바인딩하게 되면서 2초 뒤에 `obj3`을 출력하게 됩니다.
두 번째로 bind 메서드를 이용하는 방법도 있습니다!
var obj1 = {
name: 'obj1',
func: function () {
console.log(this.name);
}
};
//함수 자체를 obj1에 바인딩
//obj1.func를 실행할 때 무조건 this는 obj1로 고정해줘!
setTimeout(obj1.func.bind(obj1), 1000);
var obj2 = { name: 'obj2' };
//함수 자체를 obj2에 바인딩
//obj1.func를 실행할 때 무조건 this는 obj2로 고정해줘!
setTimeout(obj1.func.bind(obj2), 1500);
콜백 지옥 📖
말 그대로 지옥입니다. 콜백 함수 전달하는 과정이 반복되어 코드의 들여 쓰기 수준이 헬인 경우를 말합니다. 보통 비동기적인 작업을 수행할 때 발생합니다.
그럼 뭐가 문제일까요❓
유지보수 뿐만 아니라 가독성 또한 좋지 않게 됩니다.
이런 코드들은 비동기적인 작업을 수행할 때 발생한다고 하는데 비동기란 무엇일까요?
동기 vs 비동기
`동기` : 현재 실행 중인 코드가 끝나야 다음 코드를 실행하는 방식입니다.
`비동기` : 실행중인 코드의 완료 여부와 상관없이 다음 코드를 실행하는 방식입니다. ex) setTimeout, addEventLisner
그래서 비동기는 동시에 여러 작업을 수행할 수 있는 장점이 있지만, 흐름을 예측하기 어렵다는 단점이 있습니다.
콜백 지옥 해결 방안 📖
1. 기명함수
기명함수로 변환하는 방법이 있습니다!
var coffeeList = '';
var addEspresso = function (name) {
coffeeList = name;
console.log(coffeeList);
setTimeout(addAmericano, 500, '아메리카노');
};
var addAmericano = function (name) {
coffeeList += ', ' + name;
console.log(coffeeList);
setTimeout(addMocha, 500, '카페모카');
};
var addMocha = function (name) {
coffeeList += ', ' + name;
console.log(coffeeList);
setTimeout(addLatte, 500, '카페라떼');
};
var addLatte = function (name) {
coffeeList += ', ' + name;
console.log(coffeeList);
};
setTimeout(addEspresso, 500, '에스프레소');
코드 흐름이 위에서 아래로 이어지니까 가독성이 좋습니다. 근데, 한 번만 쓰고 말 텐데, 이름을 다 붙이는 건 낭비가 될 수 있습니다!
그래서 다음 게시글에서 Promise에 대해 소개해드리려고 합니다!
요약 📖
- 콜백 함수란 다른 함수로 인자를 넘겨주는 함수, 함수를 등록하기만 하고 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 호출하는 함수!
- 콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수 호출 시점, 인자의 순서에 대한 제어권을 갖습니다.
안뇽~!😊
출처 🏷️
'공부 > javascript' 카테고리의 다른 글
폴리필이란? (1) | 2024.12.12 |
---|---|
javascript 심화 7 (클로저) (0) | 2024.08.07 |
javascript 심화 6 (이벤트 루프) (0) | 2024.08.02 |
javascript 심화 5 (Promise, async, await) (0) | 2024.07.29 |
javascript 심화 3 (this, 화살표함수, call, apply, bind) (0) | 2024.07.26 |
javascript 심화 2 (호이스팅, var let const 차이점, TDZ) (5) | 2024.07.24 |
javascript 심화 1 (실행 컨텍스트) (0) | 2024.07.24 |
javascript 기본 4 (불변 객체, 얕은 복사, 깊은 복사) (0) | 2024.07.23 |