(JS) Today, I Learned : 콜백함수

호두파파·2021년 3월 8일
0

TIL

목록 보기
1/5

콜백함수

다른 코드의 인자로 넘겨주는 함수를 말한다. 콜백함수를 넘겨받은 코드는 이 콜백 함수를 필요에 따라 적절한 시점에 실행할 것이다.
콜백함수는 제어권과 관련이 깊다. 이점을 반드시 기억하시라.

//var count=0;
//var timer=setInterval(function(){
//  console.log(count);
//  if(++count>4)clearInterval(timer);
//},300);

// 위 코드를 확인하기 쉽게 아래와 같이 수정
let count = 0;
let cbfunc = function() {
  console.log(count);
  if(++count > 4) clearInterval(timer);
};
let timer = setInterval(cbFunc, 300);

setInterval에 전달한 첫 번째 인자인 cbFunc함수는 0.3초 마다 자동으로 실행될 것이다. 콜백함수의 제어권을 넘겨받은 코드는 콜백함수 호출 시점에 대한 제어권을 가진다.

인자 관련

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

코드를 해석하자면 배열에 담긴 인자를 순서대로 map메서드를 이용해 호출하고 있고, 이때 첫번째 매개변수로 익명함수를 전달한다.
우선, Array의 prototype에 담긴 map 메서드는 아래와 같은 구조를 가진다.

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

map 메서드는 첫 번째 인자로 callback 함수를 받고, 생략 가능한 두 번째 인자로 콜백함수 내부에서 this로 인식할 대상을 특정할 수 있다. thisArg를 생략할 경우 일반적인 함수와 마찬가지로 전역객체가 바인딩된다.
map 메서드는 배열의 모든 요소들을 처음부터 끝까지 하나씩 꺼내어 콜백함수를 반복 호출하고 함수 실행결과들을 모아 새로운 배열을 만든다.

this 관련

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

콜백함수는 함수다

콜백함수로 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출한다.

var obj = {
  vals : [1, 2, 3],
  logvalues : function(v, i) {
    console.log(this, v, i)l
  }
};
obj.logvalues(1, 2);
// logValues는 메서드로서 호출이 되었다. 따라서 this는 obj를 가리키고, 인자로 넘어온 1, 2가 호출된다. 
[4, 5, 6].forEach(obj.logValues); // window{...}
// 이 메서드를 forEach함수의 콜백함수로서 전달했다.
// forEach에 의해 콜백이 함수로서 호출되고, 
// 별도로 this를 지정하는 인자를 지정하지 않으므로 함수 내부에서는 this는 전역객체를 바라보게 된다.

콜백함수 내부의 this에 다른 값 바인딩하기

  • 전통적인 방식
var obj1={
  name:'obj1',
  func:function(){
    var self=this;
    return function(){
      console.log(self.name);
    };
  }
};
var callback=obj1.func();
//obj1.func를 호출하면 앞서 선언한 내부 함수가 반환되어 callback변수에 담긴다
setTimeout(callback,1000);
//위 callback을 setTimeout함수에 인자로 전달하면 1초 뒤 callback이 실행되면서 'obj1'을 출력할 것이다

obj1.func 메서드 내부에서 self 변수에 this를 담고, 익명함수를 선언과 동시에 반환했다. 이 방식은 실제로 this를 사용하지 않고 번거롭다.

  • func함수 재활용
var obj2 = {
  name : 'obj2',
  func : obj1.func
};
var callback2 = obj2.func();
setTimeout(callback2,1500);

var obj3 = {name:'obj3'};
var callback3 = obj1.func.call(obj3);
setTimeout(callback3,2000);

callback2에는 obj2의 func를 실행한 결과를 담아 이를 콜백으로 사용했다. callback3의 경우 obj1의 func를 실행하면서 this를 obj3가 되도록 지정해 이를 콜백으로 사용했다.

전통적인 방식은 불편할뿐더러, 메모리까지 낭비한다. 그래서 이젠
bind 메서드를 활용하는 것이다.

  • 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),1500);

summary

콜백함수는 다른 코드에 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수이다. 제어권을 넘겨받은 코드는 다음과 같은 제어권을 가진다.

  • 콜백함수를 호출받은 시점을 스스로 판단해서 실행한다.
  • 콜백함수를 호출할 때 인자로 넘겨줄 값들 및 그 순서가 정해져 있다. 이 순서를 따르지 않으면 엉뚱한 결과가 나온다.
  • 콜백함수의 this가 무엇을 바라보도록 할지 정해져 있는 경우도 있다. 정하지 않은 경우 전역객체를 바라본다. 사용자 임의로 this를 바꾸고 싶으면 bind메서드를 활용하면 된다.
profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글