코어자바스크립트 - 콜백 함수 / 클로져

김동하·2021년 1월 19일
0

javascript

목록 보기
49/58
post-thumbnail

콜백함수

  • 콜백 함수란 다른 코드의 인자로 넘겨주는 함수다.

제어권

호출시점

let count = 0;

const timer = setInterval(function () {

  console.log(count);
  
  if (++count > 4) {
    clearInterval(timer);
  }
}, 300);
  • setInterval을 호출할 때 두 개의 매개변수를 전달하는데 그중 첫 번째는 익명 함수, 두 번째는 300이라는 숫자. 이 코드를 조금 바꿔서
let count = 0;

const cbFunc = function () {

  console.log(count);
  
  if (++count > 4) {
    clearInterval(timer);
  }
};

let timer = setInterval(cbFunc, 1000);
  • setInterval이라고 하는 다른 코드에 첫 번째 인자로서 cbFunc를 넘겨주자 제어권을 넘겨받은 setInterval이 스스로의 판단에 따라 1초마다 익명 함수를 실행. 콜백 함수의 제어권을 넘겨 받은 코드는 콜백 함수 호출 시점에 대한 제어권을 가진다.

인자

const arr = [10, 20, 30].map(function (cur, idx) {
  console.log(cur, idx);
  return cur + 5;
});

console.log(arr); 

// 10 0
   20 1
   30 2
   [15, 25, 35]
  • map 메서드는 첫 번째 인자를 콜백 함수를 받고 두 번째 인자(생략 가능)로 콜백 함수 내부에서 this로 인식할 대상을 특정할 수 있다.
  • map 메서드는 메서드의 대상이 되는 배열의 모든 요소들을 처음부터 끝까지 하나씩 꺼내어 콜백 함수를 반복 호출하고, 콜백 함수의 실행 결과들을 모아 새로운 배열을 만든다.
  • 콜백 함수를 호출하는 주체가 map 메서드니까 어떤 순서로 호출할지 map메서드가 제어권을 갖는다.

클로저

  • 클로저는 함수와 그 함수가 선언될 당시 Lexical enviroment의 상호관계 따른 현상
  • "선언될 당시의 Lexical environment"는 실행 컨텍스트의 구성 요소 중 하나인 outerEnvironment에 해당된다.
  • LexicalEnvironment의 environmentRecord와 outerEnvironmentReference에 의해 변수의 유효범위인 스코프가 결정되고 스코프 체인이 가능해진다.
  • 내부함수에서 외부 변수를 참조하는 경우에만 "선언될 당시의 Lexical environment와의 상호관계"가 의미가 있어진다.

클로저가 아닌 함수

외부 함수의 변수를 참조하는 내부 함수

const outer = function () {

  let a = 1;
  
  let inner = function () {
    console.log(++a); // 2
  };
  
  inner();
  
};

outer();
  • inner 함수 내부에서는 a를 선언하지 않았기 때문에 environmentRecord에서 값을 찾지 못한다.
  • outerEnvironment에 지정된 상위 컨텍스트인 outer의 LexicalEnvironment에 접근해 다시 a를 찾는다.
  • console.log(++a);는 2가 출력된다.
  • outer 함수의 실행 컨텍스트가 종료되면 LexicalEnviroment에 저장된 식별자들(a, inner)를 지운다.

외부 함수의 변수를 참조하는 내부 함수(2)

const outer = function () {

  let a = 1;
  
  let inner = function () {
   return ++a
  };
  
  return inner()
  
};

const outer2 = outer();
console.log(outer2) // 2
console.log(outer2) // 2
  • inner 함수를 실행한 결과를 리턴하고 있어서 결과적으로 outer 함수의 실행 컨텍스트가 종료된 시점에서 a 변수를 참조하는 대상이 없어진다. outer의 실행 컨텍스트가 종료되고도 inner 함수를 호출할 수 있게 만들면 된다.

클로저

외부 함수의 변수를 참조하는 내부 함수(3) 클로저

const outer = function () {
  let a = 1;

  let inner = function () {
    return ++a;
  };

  return inner;
};

const outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3
  • inner 함수의 실행 결과가 아닌 inner 함수 자체를 반환했다.
  • 가바지 컬렉터는 어떤 값을 참조하는 변수가 하나라도 있다면 그 값은 수집하지 않는다.
  • 고로 '클로저는 어떤 함수 A에서 선언한 변수 a를 참조하는 내부 함수 B를 외부로 전달할 경우 A의 실행 컨텍슻트가 종료된 이후에도 변수 a가 사라지지 않는 현상'이라고 할 수 있다.

메모리 누수 관리

  • 참조 카운트를 0으로 만든다. 식별자에 참조형이 아닌 기본형 데이터(null, undefined)을 할당한다.
  • null, setInterval, eventListener로 메모리 해제

클로져 활용 - 디바운스

  • debounce는 마지막에 발생한 이벤트에 대해 한 번만 처리하는 것으로 성능 최적화에 큰 도움을 준다.
  • scroll, wheel, mousermove 등에 쓰임

클로져 활용 - 커링함수

const curry3 = function (func){
  return function (a) {
    return function (b){
      return func(a, b)
    }
  }
}

const getCurrying = curry3(Math.max)(10)
console.log(getCurrying(5)) // 10
console.log(getCurrying(15)) // 15
  • 커링 함수란 여러 개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출될 수 있게 체인 형태로 구성한 것.
  • 커링은 한 번에 하나의 인자만 전달하는 것을 원칙으로 한다.
  • 마지막 인자가 전달되기 전까지 원본 함수가 실행되지 않는다.

지연 실행

const getInformation = function (baseUrl) {
  return function (path) {
    return function (id) {
      return fetch(baseUrl + path + '/' + id);
    };
  };
};

//ES6
const getInformation = (baseUrl) => (path) => (id) =>
  fetch(baseUrl, path + '/' + id);
  • 커링을 이용해서 서버 요청할 때 효율적으로 가능하다.
  • 와 이렇게 HTTP요청을 할 수 있다니 가슴이 뛴다...
profile
프론트엔드 개발

1개의 댓글

comment-user-thumbnail
2021년 1월 27일

axios의 baseurl이나 interceptor 같은 기능들 찾아보세여

답글 달기