[JS] 콜백함수

2022. 8. 7. 00:03학습/JavaScript

반응형

JS 콜백함수

콜백함수

다른 코드의 인자로 넘겨주는 함수를 말하며, 인자로 넘겨주면서 제어권도 위임을 진행합니다.

이를 통해서 함수가 실행되는 시점을 조절할 수 있습니다.

콜백함수의 제어권


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

cbFunc()는 사용자가 호출하고 제어하지만

timer에서 cbFunc()setInterval에 의해서 호출되고 제어되고 있습니다.

콜백함수의 this


Array.prototype.map(callback[, thisArg])

map의 경우 첫 번째 인자를 콜백함수를 받으며 다음 인자로 this를 설정합니다.

  • map을 직접 구현한 코드

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);
        mappedArr[i] = mappedValue;
    }
    return mappedArr;
};

  • this를 설정하지 않으면 전역 객체를 가리키기도 하며 따로 정의가 되어있기도 합니다.

setTimeout(function () { console.log(this); }, 300);
//Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}

[1, 2, 3, 4, 5].forEach(function (x) {
    console.log(this);
});
//Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}

document.body.innerHTML += '<button id="a"> 클릭 </button>';
document.body.querySelector('#a').addEventListener('click', function (e) {
    console.log(this,e);
});
// <button id="a"> 클릭 </button>
// PointerEvent {isTrusted: true, pointerId: 1, width: 1, height: 1, pressure: 0, …}

  • addEventListener는 호출한 HTML 엘리먼트가 this가 됩니다.

콜백함수는 함수다!

  • 객체의 메서드가 콜백함수로 전달되어도 메서드가 아닌 함수로 적용된다는 말입니다.
    • 그렇다면 this는 전역객체이거나 따로 설정을 진행할 것입니다.

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

  • self = this 사용
    • 안쓰는 방법입니다.
    
    var obj1 = {
        name: 'obj',
        func: function () {
            var self = this;
            return function () {
                console.log(self.name);
            };
        }
    };
    var callback = obj1.func();
    setTimeout(callback, 1000);
    
    
  • bind
  • 
      var obj1 = {
              name: 'obj',
              func: function () {
                  console.log(this.name);
              }
          };
      setTimeout(obj1.func.bind(obj1), 10);//obj
      var obj2 = {
          name: 'osdn'
      }
      setTimeout(obj1.func.bind(obj2), 10);//osdn
    
    

콜백 지옥과 비동기 제어

콜백지옥

  • 콜백 함수를 익명함수로 전달하는 과정에서 들여쓰기가 너무 많아져 코드의 가독성이 떨어지는 현상입니다.
  • 함수의 흐름이 아래서 위로 향하기 때문에 불안정합니다.

동기적인 코드

  • 현재 실행 중인 코드가 완료된 이후에 다름 코드를 실행하는 방법을 뜻합니다.
  • CPU에 의해 즉시 처리 가능한 대부분의 코드입니다.

비동기적인 코드

  • 코드의 실행 완료 여부와 무관하게 다음 코드로 넘어갑니다.
    • 사용자의 요청에 의해 함수의 실행을 보류 (setTimeout)
    • 사용자의 직접적인 개입이 있을 때 함수를 실행 (addEventListener)
    • 웹 브라우저의 요청에 응답이 왔을 때 (XMLHttprequest) 등등

콜백지옥 해결방법

  • 익명함수가 아닌 기명함수로 사용하기
    • 위에서 아래로 흘러가는 자연스러운 코드 구조가 됩니다.
    • But, 일회성 함수를 다 등록해야 하는 번거로움이 있습니다.
  • [ES6] Promise
    • resolve, reject 함수를 호출하는 구문에 따라 then, catch 구문으로 넘어가서 비동기적인 작업이 진행됩니다.
  • [ES6] Generator
    • '*'가 붙은 함수가 Generator함수입니다.
    • Generator함수 실행 시 Iterator가 반환이 되는데 이는 next라는 메서드를 갖고 있습니다.
    • next 메서드가 호출되면 Generator함수 내부의 yield 함수의 실행을 멈춥니다.
    • 이렇게 next 함수를 작업이 완료될 때마다 실행하면 순차적으로 진행됩니다.
  • [ES2017] Promise + Async/await
    • 비동기 작업을 하고자 하는 함수에 async를 표기하고서
    • 비동기 작업이 필요할 때마다 await을 표기해서 해당 작업이 resolve가 되야 다음으로 진행됩니다.

이 글은 "코어자바스크립트" 내용에 기반하여 작성한 글입니다.
잘못된 부분이나 이해가 잘못된 부분에 대해서는 댓글로 써 주시면 감사하겠습니다!

반응형

'학습 > JavaScript' 카테고리의 다른 글

[JS] 프로토타입  (0) 2022.08.08
[JS] 클로저  (0) 2022.08.07
[JS] this  (0) 2022.08.06
[JS] 실행 컨텍스트  (0) 2022.07.31
[JS] 원시타입과 참조타입의 차이  (0) 2022.07.16