[함수] - 고차 함수와 콜백 함수

Donggu(oo)·2022년 11월 22일
0

JavaScript

목록 보기
18/49
post-thumbnail

일급 객체


일급 객체(first-class citizen)란?

  • 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다. 보통 변수에 할당, 다른 함수의 전달인자로 전달, 다른 함수의 결과로 리턴 같은 연산을 지원할 때 일급 객체라고 한다.
  • 자바스크립트에서 함수는 일급 객체이다.

1. 고차 함수


  • 매개변수(parameter)를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차 함수라고 한다.
  • 고차 함수는 매개변수(parameter)를 통해 전달받은 콜백 함수의 호출 시점을 결정해서 호출(invoke)한다. 즉, 콜백 함수는 고차 함수에 의해 호출되며 이때 고차 함수는 필요에 따라 콜백 함수에 인수를 전달할 수 있다. 따라서 고차 함수에 콜백 함수를 전달할 때 콜백 함수를 호출하지 않고 함수 자체를 전달해야 한다.
  • 고차 함수라는 용어를 '함수를 전달인자로 받는 함수'라고 사용할 경우 '커링 함수'라고도 한다. 그러나, 커링 함수는 고차 함수에 포함되는 개념이다.
// 함수 funcA는 콜백 함수인 funcB를 외부에서 매개변수를 통해 전달받은 '고차 함수'이다.
function funcA(callback) {
  callback()
}

// 함수 funcB는 동기적으로 실행되고 있는 함수 funcA의 '콜백 함수'이다.
function funcB() {
  console.log('내가 콜백함수다!')
}

console.log(funcA(funcB))  // '내가 콜백함수다!'

2. 콜백 함수(Callback Function)


  • 함수의 매개변수(parameter)를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 한다.
  • 다른 함수(caller)의 전달인자(argument)로 전달되는 함수를 콜백 함수라고 한다.
  • 콜백 함수는 비동기 처리와 배열 고차 함수에서 사용된다.

1) 콜백 함수를 사용하는 이유

  • 아래 예제의 함수들은 반복하는 일은 변하지 않고 공통적으로 수행하지만(같은 for문을 사용) 반복하면서 하는 일의 내용은 다르다. 즉, 함수의 일부분만이 다르기 때문에 매번 함수를 새롭게 정의해야 한다.
// repeat 함수는 매개변수를 통해 전달받은 숫자만큼 반복하며 console.log(i)를 호출한다.
// 이때 repeat 함수는 console.log(i)에 강하게 의존하고 있어 다른 일은 할 수 없다.
// 따라서 만약 repeat 함수의 반복문 내부에서 다른 일을 하고 싶다면 함수를 새롭게 정의해야 한다.

// n번만큼 반복하며 i를 출력하는 함수
function repeat1(n) {
    for (let i = 0; i < n; i++) {
        console.log(i)
    }
}

// n번만큼 반복하며 i가 홀수인 경우만 출력하는 함수
function repeat2(n) {
    for (let i = 0; i < n; i++) {
        if (i % 2 === 1)
            console.log(i)
    }
}

2) 다른 함수를 인자로 받는 경우

  • 외부에서 정의된 다른 함수를 인자로 전달할 수 있다.
// 함수 doubleNum은 다른 함수를 인자로 받는 고차 함수이다.
function doubleNum(func, num) {
  return func(num);
}

// 함수 doubleNum의 첫 번째 인자 func에 함수 double이 들어갈 경우 함수 double은 콜백 함수이다.
function double(num) {
  return num * 2;
}

console.log(doubleNum(double, 4));  // 8
// 함수 repeat은 다른 함수를 인자로 받는 고차 함수이다.
function repeat(num, func) {
    for (let i = 0; i < num; i++) {
        func(i);
    }
}

// 함수 logAll의 두 번째 인자 func에 함수 logAll이 들어갈 경우 함수 logAll은 콜백 함수이다.
function logAll(i) {
    console.log(i);
}

repeat(5, logAll);  // 0, 1, 2, 3, 4
  • 또한 콜백 함수는 정의된 함수 뿐만 아니라 인자에 익명 함수로도 전달 가능하다.
// case2. 콜백 함수를 익명 함수로 바로 인자로 전달하는 경우
function repeat(func, n) {
    for (let i = 0; i < n; i++) {
        func(i);
    }
}

repeat(5, function(i) { // 익명 함수를 콜백 함수로 사용
    console.log(i)
});

3) 함수를 리턴하는 경우

// 함수 adder는 인자 한 개를 입력받아 익명 함수를 리턴하는 고차 함수이다.
function adder(added) {
  return function (num) {
    return num + added;  // 입력 받은 인자와 added를 더한 값을 리턴
  };
}

// adder(5)는 함수이므로 함수 호출 연산자 '()'를 사용할 수 있다.
console.log(adder(5)(3));  // 8

// javascript에서 함수는 일급 객체이기 때문에 adder가 리턴하는 함수를 변수에 저장할 수 있다.
const add3 = adder(3);
console.log(add3(2));  // 5

4) 함수를 인자로 받고, 함수를 리턴하는 경우

// 함수 doubleAdder는 인자 한 개와 다른 함수(콜백 함수)를 입력받아 익명 함수를 리턴하는 고차 함수이다.
// 함수 doubleAdder의 매개변수 func는 함수 doubleAdder의 콜백 함수이다.
function doubleAdder(added, func) {
  const doubled = func(added);
  return function (num) {
    return num + doubled;
  };
}

// 함수 doubleAdder의 두 번째 인자 func에 함수 double이 들어갈 경우 함수 double은 콜백 함수이다.
function double(num) {
  return num * 2;
}

// doubleAdder(5, double)는 함수이므로 함수 호출 기호 '()'를 사용할 수 있다.
console.log(doubleAdder(5, double)(3));  // 13

// javascript에서 함수는 일급 객체이기 때문에 doubleAdder가 리턴하는 함수를 변수에 저장할 수 있다.
const addTwice3 = doubleAdder(3, double);
console.log(addTwice3(2));  // 8

0개의 댓글