TIL 85 | 코어자바스크립트(3) 콜백 함수

meow·2020년 12월 8일
0

JavaScript

목록 보기
33/46

시대의 명작 코어 자바스크립트를 읽고 자바스크립트 마스터에 도전합니다...
코어 자바스크립트(web) : 콜백

콜백 함수?

콜백 함수(callback function)는 다른 코드(함수 또는 메서드)의 인자로 넘겨주는 함수이다. 함수 실행에 대한 제어권도 함께 위임한다. 위임받은 코드는 자체적인 로직에 의해 이 콜백 함수를 적절한 시점에 실행한다.

제어권

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

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

2) 콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수를 호출할 때 인자에 어떤 값들을 어떤 순서로 넘길 것인지에 대한 제어권을 가진다.

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

3) 콜백 함수의 this가 무엇을 바라보게 할지 정해진 경우도 있다. 정하지 않은 경우에는 전역객체를 바라본다. 사용자가 임의로 this를 바꾸고 싶은 경우 bind 메서드를 사용한다.

Array.prototype.map = function (callback, thisArg) {
  var mappedArr = [];
  for (var i = 0; i < this.length; i++) {
    var mappedValue = callback.call(thisArg || window, this[i], i, this);
    mapperArr[i] = mappedValue;
  }
  return mappedArr;
}

제어권을 넘겨받을 코드에서 call/apply 메서드의 첫 번째 인자에 콜백함수 내부에서의 this가 될 대상을 명시적으로 바인딩한다.

콜백 함수는 함수다

어떤 함수의 인자에 객체의 메서드를 전달하더라도 이는 결국 메서드가 아닌 함수일 뿐이다! 콜백이 함수로서 호출되면 함수 내부의 this는 전역객체를 바라본다.

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에 다른 값 바인딩

var self = this

var obj1 = {
  name: 'obj1',
  func: function () {
    var self = this;
    return function () {
      console.log(self.name);
    };
  }
};
var callback = obj1.func();
setTimeout(callback, 1000); 

함수 재활용

...
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);

this를 사용하지 않은 경우(재활용 불가!)

var obj1 = {
  name: 'obj1',
  func: function () {
    return function () {
      console.log(obj1.name);
    };
  }
};
setTimeout(obj1.func, 1000); 

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);

콜백 지옥과 비동기 제어

콜백 지옥이란 콜백 함수를 익명으로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들어질 정도로 깊어지는 현상이다. 보통은 이벤트 처리나 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장한다.

콜백 지옥 해결 방법

1. 기명 함수로 변환 : 코드 가독성을 높일 수 있다.
2. Promise : new 연산자와 함께 호출한 Promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만 내부에 resolve 또는 reject 함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 then 또는 catch로 넘어가지 않는다.
3. Generator : next 메서드를 호출하면 Generator 함수 내부에서 가장 먼저 등장하는 yield에서 함수의 실행을 멈춘다. 비동기 작업이 완료되는 시점마다 next를 호출하면 내부의 소스를 위에서 아래로 순차적으로 할 수 있다.
4. async/await : 비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 표기하는 것 만으로도 뒤의 내용을 Promise로 자동 전환하고 해당 내용이 resolve된 이후에 다음으로 넘어간다.

profile
🌙`、、`ヽ`ヽ`、、ヽヽ、`、ヽ`ヽ`ヽヽ` ヽ`、`ヽ`、ヽ``、ヽ`ヽ`、ヽヽ`ヽ、ヽ `ヽ、ヽヽ`ヽ`、``ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ`ヽ`ヽ、ヽ、ヽ`ヽ`ヽ 、ヽ、ヽ、ヽ``、ヽ`、ヽヽ 🚶‍♀ ヽ``ヽ``、ヽ`、

0개의 댓글