콜백 함수란?
1. 콜백 함수의 정의
- 콜백 함수는 다른 코드의 인자로 넘겨주는 함수입니다. 즉, 콜백 함수는 함수나 메서드가 필요할 때 호출할 수 있도록, 다른 함수에 전달됩니다. JavaScript에서는 setTimeout, forEach와 같은 함수가 콜백 함수를 받아들이는 대표적인 예입니다.
// setTimeout
setTimeout(function() {
console.log("Hello, world!");
}, 1000);
// forEach
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function(number) {
console.log(number);
});
2. 콜백 함수의 제어권
- 콜백 함수를 넘겨받은 코드는 언제, 어떻게 콜백 함수를 호출할지에 대한 제어권을 가집니다. 즉, 호출 시점과 방식은 콜백 함수를 사용하는 코드(forEach, setTimeout 등)에 의해 결정됩니다.
var count = 0;
var timer = setInterval(function() {
console.log(count);
if (++count > 4) clearInterval(timer);
}, 300);
- 위 코드에서 setInterval은 콜백 함수가 0.3초마다 호출되도록 제어권을 가지고 있습니다.
3. 콜백 함수와 인자
- 콜백 함수의 인자는 호출되는 함수의 규칙에 따라 전달됩니다. 예를 들어, Array.prototype.map 함수는 콜백 함수에 배열의 요소와 해당 요소의 인덱스를 인자로 넘깁니다.
-
var newArr = [10, 20, 30].map(function(currentValue, index) {
console.log(currentValue, index);
return currentValue + 5;
});
console.log(newArr);
// -- 실행 결과 --
// 10 0
// 20 1
// 30 2
// [15, 25, 35]
- 콜백 함수의 인자 순서를 바꾸면 예상치 못한 결과가 발생할 수 있습니다.
-
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]
- 이처럼 콜백 함수의 인자는 정의된 규칙에 맞게 작성해야 합니다.
4. 콜백 함수와 this
- 콜백 함수도 일반 함수와 마찬가지로 기본적으로 this는 전역 객체를 참조합니다. 그러나 콜백 함수에 this를 명시적으로 지정할 수 있습니다.
Array.prototype.mapaaa = function(callback, thisArg) {
var mappedArr = [];
for (var i = 0; i < this.length; i++) {
var mappedValue = callback.call(thisArg || globalThis, this[i]);
mappedArr[i] = mappedValue;
}
return mappedArr;
};
const a = [1, 2, 3].mapaaa(function(item) {
return item * 2;
});
console.log(a); // [2, 4, 6]
- call 메서드를 사용해 this를 명시적으로 지정할 수 있습니다. 이를 통해 제어권을 넘겨받는 코드에서 콜백 함수의 this를 원하는 대로 설정할 수 있습니다.
// setTimeout은 기본적으로 전역 객체를 참조합니다.
setTimeout(function() {
console.log(this); // Window { ... }
}, 300);
// forEach도 마찬가지로 전역 객체를 참조합니다.
[1, 2, 3, 4, 5].forEach(function(x) {
console.log(this); // Window { ... }
});
// addEventListener는 this를 이벤트 대상 객체로 설정합니다.
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
console.log(this, e); // <button id="a">클릭</button> MouseEvent
});