콜백 함수 : 다른 코드의 인자로 넘겨주는 함수!
call back = call(부르다) + back(되돌아오다) = 되돌아와서 호출해줘!
콜백 함수는 다른 코드(함수 또는 메서드)에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수이다!
위임받은 코드는 자체적으로 내부 로직에 의해 이 콜백 함수를 적절한 시점에 실행한다.
1. 호출 시점에 대한 제어권
setInterval 함수 : 반복해서 매개변수로 받은 콜백 함수의 로직을 수행
+
clearInterval 함수 : setInterval 함수의 로직에서 벗어나게 해준다.
setInterval( handler 함수, 반복할 초 간격, 콜백 함수에 전달할 추가 인수들입니다)
로사용 가능하다
위의 코드를 살펴 보면 setInterval 함수의 호출 시점 제어권이
setInterval 함에게 0.3초 동안 제공된 것을 볼 수 있다.
위의 코드를 살짝 변형해
cbFunc()를 직접 사용할 경우 호출 주체는 사용자이고,
제어권도 사용자에게 있는걸 볼 수 있다.
하지만,
var timer = setInterval(cbFunc, 300)으로 사용할 경우
호출 주체가 setInterval 함수가 되, 제어권도 setInterval
함수에게 있는걸 볼 수 있다.
2. 인자 제어권
map을 사용하기 위해서는
map(element, index, array)를 정해진 순서대로
사용해야 한다.
사람이 input 순서를 바꿀 수 없다.
(다른 함수들도 마찬가지로 인자 값 순서가 정해져 있다)
(아는 내용이라 간단하게 적고 넘어가겠습니다.)
3. this 제어권
저번 시간에 addEventListener를 만든 개발자는
this를 가리키는 대상을 addEventListener를 호출한
대상으로 설정했다고 배웠다.
addEventListener처럼 우리도 this의 제어권을
함수에게 주는 메서드를 구현해보자
callback.call(thisArg || global, this[i])
로 함수를 호출한 대상이 있으면
그 대상을 가리키고
this로 없으면 global로
this를 제어할 수 있다.
객체에 함수가 존재하고
forEach와 같은 콜백함수를 사용해서
객체 안 함수를 매개변수로 사용할 경우
obj 객체가 아닌
함수가 매개변수의 input 값으로
들어가기 때문에
(
key에 따른 value
(logValues) (function)
즉, value가 input으로 들어가기 때문에
)
객체가 아닌 Node의 전역 객체인
global을 this가 가리키게 된다.
콜백함수 내부 this에 다른 값을
Binding 하는 방법
1. self
obj.func()로
함수를 호출할 경우
위와 같이 return 구문에 작성된
함수를 callback 변수에 담겠다는 의미이다.
따라서,
setTimeout(callback, 1000)은
같이 함수가 input 값으로 들어가게 된다.
그리고 self에 담긴 this가 유지 돼
this가 객체(obj)를 가르키게 만드는 방식이다.
2. call
call 함수를 활용해 this binding 방식으로
this가 객체를 가리키게 하면
obj.func.call(obj2)
에서 call함수로
사용자가 this로
가리키고 싶은 대상을
obj2로 바꿔줬기 때문에
console.log(self.name)의 결과로
"obj2"가 출력될 것 이다.
3. bind
bind 함수는 this binding 이뤄진 후
변수나 함수로 받아줘야 하는데
그 점을 활용해 함수의 input 값으로
넣어주면
bind(obj1)을 주어 this가 가리켜야 할 대상을
obj1으로 지정했기 때문에
console.log(this.name)에서
"obj1"이 출력된다.
위의 코드를 활용하면,
obj1의 함수인 func를 호출했더라도
bind(obj2)해주었기 때문에
this가 obj2를 가리킬 것이다.
콜백 지옥과 비동기 제어
콜백 지옥
- 익명 함수로 절달하는 과정이 반복되어 코드의 들여쓰기 수준이 지옥 수준인 경우
- 이벤트 처리 및 서버 통신과 같은 비동기적 작업을 수행할 때 발생합니다.
- 가독성이 지옥이라, 수정이 어렵다.
ex)
동기(sync) VS 비동기(async)
동기
- 실행 중인 코드가 끝나야 다음 코드를 실행하는 방식
- CPU의 계산에 의해 즉시 처리가 가능한 대부분의 코드
비동기
- 실행 중인 코드의 종료 여부와 무관하게 즉시 다음 코드 실행
- 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 모두 비동지적 코드
- 서버 - 클라이언트, 서버 - web 통신에 들어가는 대부분의 코드
ex) setTimeout, addEventListner
그래서, 복잡도가 올라갈 수록 비동기적 코드의 비중이 늘어난다.
비동기 표현 약속
-> 순서를 보장하지 않는 작업
그런데! 비동기 함수 끼리 순서가 필요하다면?
->비동기 작업의 동기적 표현이 필요하다!
비동기 작업의 동기적 표현 방법은
ES6 : Promise, Generator
Promise
Promise : 비동기 처리에 대해, 처리가 끝나면 알려달라는 '약속'
- new 연산자로 호출한 Promise의 인자로 넘어가는 콜백은 바로 실행된다.
- 그 내부의 resolve, reject 함수 호출 구문이 있을 경우 둘 중 하나가 실행되기
전까지는 다음(then), 오류(catch)로 넘어가지 않는다.
- 비동기 작업이 완료될 때 비로소 resolve, reject 호출이 된다.
Generator : 반복할 수 있는 객체 생성
작업이 완료되는 시점마다 next 메서드를 호출해주면
Generator 함수 내부소스가 위 -> 아래 순차적(yield(미루다) 부분)으로 진행된다.
사용방법 : function* (별표 표시가 Generator를 표시한다.)
next()가 호출되면 yield 뒷 부분 로직이 실행되는 걸 볼 수 있다.
ES7 : async / await
async 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다
await를 붙여주면 된다.
'JavaScript 강의' 카테고리의 다른 글
5-2 Class (0) | 2024.08.18 |
---|---|
5-1 DOM (0) | 2024.08.18 |
3-3 this(정의, 활용법, 바인딩, call, applay, bind) (0) | 2024.08.14 |
3-2 실행컨텍스트(스코프, 변수, 객체, 호이스팅) (0) | 2024.08.14 |
3-1 데이터 타입 종류 및 메모 (0) | 2024.08.13 |