TIL 28 JavaScript - 콜백 함수(callback function)

Leo·2021년 5월 13일
0

Javascript

목록 보기
12/17
post-thumbnail

콜백함수란?

콜백함수는 다른 코드의 인자로 넘겨주는 함수이다. 예를 들어 어떤 함수 X를 호출하면서 ‘특정 조건일 때 함수 Y를 실행해서 나에게 알려달라’는 요청을 함께 보낸다. 이 요청을 받은 함수 X는 특정 조건이 갖추어졌는지 판단하고 Y를 직접 호출하고, 이때 호출되는 Y가 콜백함수가 된다.

즉, 함수 Y의 제어권은 함수 X에 있고 이처럼 콜백 함수는 제어권과 관련이 깊다.

제어권

콜백 함수의 제어권을 넘겨받은 코드는 다음과 같은 제어권을 갖는다.

  1. 콜백 함수를 호출하는 시점에 대한 제어권
  2. 콜백 함수를 호출할 때 인자로 넘겨 줄 값들을 어떤 순서로 넘길 것인지에 대한 제어권.
  3. 콜백 함수의 this가 무엇을 바라보도록 정할 지에 대한 제어권. 콜백함수도 결국 함수이기 때문에 정하지 않았을 경우 전역 객체를 바라본다.

1. 호출 시점

var count = 0;
var cbFunc = function () {
  console.log(count);
  if(++count > 4) clearInterval(timer);
}

var timer = setInterval(cbFunc, 300);

cbFunc함수가 setInterval함수에 의해 0.3초 마다 자동으로 실행되며 1을 더한 값이 출력된다. 여기서 cbFunc함수의 제어권이 setInterval함수에 있는데 cbFunc함수가 콜백 함수이다.

콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수 호출 시점에 대한 제어권을 가진다.

2. 인자

var newArr = [10, 20, 30].map(function(currentValue, index) {
  console.log(currentValue, index);
  return currentValue + 5;
});

console.log(newArr);

map메서드는 첫 번째 인자로 콜백 함수를 받고 생략 가능한 두 번째 인자로 콜백 함수 내부에서 this로 인식할 대상을 특정할 수 있다.

콜백 함수의 첫 번째 인자에는 배열의 요소 중 현재값, 두 번째 인자에는 현재값의 인덱스가, 세 번째 인자에는 map 메서드의 대상이 되는 배열 자체가 담긴다.

Array.prototype.map(callback[, thisArg])
callback: function(currentValue, index, array)

그리고 위 코드가 실행되면 배열의 각 요소를 처음부터 끝까지 꺼내어 콜백 함수를 실행하고 newArr에는 [15, 25, 35]라는 새로운 배열이 담긴다.

그런데 여기서 map메서드의 콜백 함수의 첫 번째 인자와 두 번째 인자의 단어를 바꾸어서 실행해도 문제가 없을 것이라고 생각할 수도 있다. 사람은 ‘index’,. ‘currentValue’ 같이 단어로 접근하기 쉽기 때문이다. 하지만 컴퓨터는 첫 번째, 두 번째에 순서에 의해 처리를 하기 때문에 사용자가 명명한 이름과는 상관없이 순서에 의해 작업을 처리한다.

var newArr = [10, 20, 30].map(function(index, currentValue) {
  console.log(currentValue, index);
  return currentValue + 5;
});

console.log(newArr);

위 코드를 실행했을 때 currentValue라고 명한 인자의 위치가 두 번째이고, 컴퓨터는 이름과는 상관없이 순서에 의해 인덱스값으로 인식한다. 이처럼 콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수를 호출할 때 인자에 어떤 값들을 어떤 순서로 넘길 것인지에 대한 제어권을 가진다.

3. this

콜백 함수도 함수이기 때문에 기본적으로 전역 객체를 참조하지만 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조하게 된다.

[1, 2, 3, 4, 5].forEach(function(x){
  console.log(this); // window{...}
})

document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
  console.log(this, e); // <button id="a">클릭</button>, MouseEvenr{...}
})

forEach메소드가 사용된 코드에서는 별도의 인자로 this를 넘겨주지 않았기 때문에 전역객체를 가리킨다.

addEveneListener는 콜백함수를 호출할 때 call 메서드 내부에서 첫 번째 인자에 addEventListener메서드의 this를 그대로 넘기도록 정의돼 있기 때문에 this가 호출 주체인 HTML 엘리먼트를 가리키게된다.

Reference

  • 코어자바스크립트(정재남 지음)
profile
느리지만 확실하게

0개의 댓글