본문 바로가기

자바스크립트의 정석 🟡

[자바스크립트] callback 정리 ✨

참고자료: 인프런-코어자바스크립트

 

학습 페이지

 

www.inflearn.com

 

 

⭐️ 콜백(callback)

- '회신하다/답신하다'

- 제어권을 넘겨주는 함수

 

 


 

📚 제어권 위임하는 경우 세 가지

- 실행시점

- 매개변수

- this

 

 

📚 제어권 위임- 실행시점

setInterval(function(){
  console.log('1초마다 실행됩니다')
}, 1000);

- setInterval은 일정 시간 간격으로 한번씩 함수를 실행시켜주는 함수

- 주기함수 호출(인자1: 콜백함수, 인자2: 주기); = setInterval(callback, milliseconds)

- 콜백함수가 함수가 실행되는 시점에 setInterval에게 제어권을 넘겨줌으로써 함수가 일정시간이 지난 시점에 함수가 실행됨

- 만약 setInterval이라는 함수가 없다면, 수시로 1초 있다가 함수 실행하는 것을 반복해야 함. 그렇기 하기에는 힘드니까 setInterval에게 맡기는 것임

 

 

 

 

📚 제어권 위임 - 매개변수

var arr = [1, 2, 3, 4, 5];
var entries = [];
arr.forEach(function(v, i){
  entries.push([i, v, this[i]]);
}, [10, 20, 30, 40, 50]);
console.log(entries);

- forEach라는 메서드는 배열에 있는 수를 하나씩 꺼내 첫번째 매개변수에 값, 두번째 매개변수에 index를 부여하며 함수를 실행시킴

- arr 이라는 배열에 value, index 값을 프로퍼티로 인덱스, 배열 값, this[i]를 하나씩 부여하며 실행시킴 -> this[i]를 무시하고 [0, 1], [1, 2], [2, 3] ... 이렇게 하나의 배열이 만들어짐

- 여기서 this[i]까지 관여하여 결과값을 알아내면, [0, 1, 10], [1, 2, 20], [2, 3, 30] ... 의 결과가 나옴. 그렇다면 두번째 인자([10, 20, 30, 40, 50])들이 this로 넘어간 것을 알 수 있음. 여기서 알 수 있는 것은 forEach라는 함수는 첫번째 인자인 콜백함수를 받고, 그 다음 두번째 인자에 thisArguments를 받는다는 것을 알 수 있음

✅ forEach(인자1: 콜백함수, 인자2: this로 인식할 대상(생략가능))

 

 

📌 MDN에서 forEach에 대해 알아보자

 

- 인자들의 값을 forEach가 정해준 규칙에 따라 매개변수를 순서를 정할 수밖에 없음

 

 

 

💻 잘못된 코드)

var arr= [1, 2, 3, 4, 5];
arr.forEach(function(index, value){
  console.log(index, value);
})

- 이런 식으로 매개변수에 개발자 마음대로 첫 번째 매개변수로 index, 두번째 매개변수로 value로 정해 순서를 정해봤자 forEach 메서드의 정해진 순서가 value, index 순이기 때문에 개발자 마음대로 매개변수의 순서를 바꿀 순 없음.

- 즉, 이 코드로 본다면 index라는 변수 이름은 가진 value 값, value라는 변수 이름을 가진 index일 수밖에 없는 것

이런 의미에서 내가 제어권을 넘겨주고자 하는 대상의 규칙에 따라야만 동작을 제대로 할 수 있다는 것에 매개변수에 제어권을 위임한다는 의미가 됨

 

 

 

 

 

📚 제어권 위임 - this

document.body.innerHTML = '<div id="a">abc</div>';
function cbFunc(x){
  console.log(this, x);
}

document.getElementById('a'). addEventListener('click', cbFunc);

- id가 a인 엘리먼트를 클릭했을 때, cbFunc이 실행되도록 addEventListner에 넘기고 있음

- 콜백함수 내부에서는 그저 this와 인자 x를 출력하고 있음

 

 

 

- cbFunc을 호출했을 때, this에는 클릭한 대상인 id가 a인 div가 출력되고, x에는 PointEvent라고 해서 click event에 대한 이벤트 객체가 출력됨. 왜냐하면, addEventListner가 그렇게 정의해서 이런 결과가 출력되는 것. 

- addEventListner가 콜백함수를 받을 때 this는 eventTarget으로 하고 콜백함수의 첫번째 인자에는 event 객체를 넘겨주도록 정해 놓았음.

✅ MDN에서 addEventListner 함수는 첫번째 인자로 type, 두번째 인자로 콜백함수를 받음

 

📌 그럼, 만약에 콜백함수 안의 this를 위의 내용 대신 obj로 바꾸고 싶다면, bind(obj)를 걸어주면 this가 가르키는 값이 바뀌게 됨

document.getElementById('a').addEventListner('click', cbfunc.bind(obj);

 

 

 


 

📌 정리

- 다른 함수 (A)의 인자로 콜백함수(B)를 전달하면, A가 B의 제어권을 갖는다.

- A에 미리 정해놓은 방식에 따라 B를 호출한다.

- 미리 정해놓은 방식이란 어떤 시점에 콜백을 호출할지, 인자에는 어떤 값을 지정할지, this에 무엇을 바인딩할지 등이다.

 


 

 

 

‼️ 주의

 

var arr = [1, 2, 3, 4, 5];
var obj = {
  vals: [1, 2, 3],
  logValues: function(v, i){
    if(this.vals){
      console.log(this.vals, v, i)
    } else {
      console.log(this, v, i);
    }
  }
}

메서드로써 호출, obj.logValues(1, 2);

콜백함수로서 전달, arr.forEach(obj.logValues);

만약 이 코드 위에 어떤 this를 받고 있을 때 this가 가르키는 것은 첫번째 경우처럼 this는 점 앞에 있는 obj가 될 것이고 logValues는 메서드로서의 역할을 가지고 있음

- 한편, 똑같은 obj.logValues를 forEach 메서드 안에 사용하고 있더라도 이것은 콜백함수로써 전달한 것이지 메서드 호출의 역할을 할 수 없음.

-> 결과값

undefined 1 0
undefined 2 1
undefined 3 2
undefined 4 3
undefined 5 4

this가 가르키는 것을 obj로 지정할 수가 없음. 그래서, 여기서 만약 this를 obj를 가르키게 하고 싶다면 bind 함수를 사용해 (obj.logValues.bind(obj));로 수정하면 됨