본문 바로가기
TIL

2024.03.27 26일차 Javascript 다중 매개변수, 콜백함수

by Song.dev 2024. 3. 27.

 

 

다중 매개변수와 다중 반환값

  • 인자 개수 > 매개변수 개수 일 때 초과하는 인자는 전달 안 됨
    ex ) 아래의 코드에서 2는 전달 안 됨
function add2(n1, n2) {
  return n1 + n2;
}

var r1 = add2(5, 9, 2);

 

매개변수가 3개인 새로운 함수를 만들 것인가?

만약 n개의 정수 합을 구해주는 함수를 만들어야 한다면?

하나의 함수에서 매개변수 개수가 동적이라면 더 효율적일 것

 

== > 파라미터에 집합자료형(배열, 객체)를 전달

 

ES6 - spread 문법

  • 여러 인자를 하나의 배열로 매개변수에 전달
  • spread 문법을 두 번 쓸 수는 없음
    어디까지가 numbers 매개변수인지 구분할 수 없기 때문
// ES6 - spread 문법
function addAllES6(...numbers) {
  console.log(numbers);                // [ 10, 20, 30 ]
  var total = 0;
  for (var n of numbers) {
    total += n;
  }
  return total;  
}

var r3 = addAllES6(10, 20, 30);
console.log(`r3: ${r3}`);               // r3: 60

 

 

function addAllES6(...numbers, ...others) { }      // 불가

function addAllES6(first, second, ...numbers) { }  // 가능

 

 

다중 반환값

  • 파라미터가 여러 개여도 리턴은 하나의 값만 가능
  • 리턴 값으로 두 가지 값을 보낼 때 마지막 값만 전달됨
  • 집합 자료형을 리턴하면 하나의 집합자료형이라서 여러 결과값 모두 전달 가능 

 

function arithmeticOperate(n1, n2) {
  var subResult = n1 - n2;
  var multiResult = n1 * n2;
  var divResult = n1 / n2;
  return {
    add: add2(n1, n2),     // add2 함수 재사용
    div: divResult, 
    multi: multiResult,
    sub: subResult,
  };
}

 

 

 

**  함수의 리턴값이 객체라면 바로 프로퍼티(마침표 표기법)으로 가져와도 됨

var r6 = arithmeticOperate(5, 3).multi;

 

**  프로퍼티 이름을 생략하고 변수명을 값으로 사용하면

      자동으로 변수명을 프로퍼티 이름으로 사용

function calcNumbersTotalAndAverage(...numbers) {
  var total = 0;
  for(var n of numbers) {
    total += n;
  }
  
  return {
    total,         // ES6문법 변수명을 키로 자동으로 사용함
    avg: total / numbers.length,
  };
}

 


콜백 함수

콜백

  • 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수
  • 매개 변수를 통해 외부에서 콜백 함수를 전달받은 함수를 고차 함수라고 함

 

**  코드를 읽는 시점 말고 나중에 호출

     = 함수 만들어 놓고 특정 상황에 호출 ( ex. 마우스 클릭, 키보드 d키 다운, … )

 

짝수를 구하는 함수

function showEvenNumber(n) {
    for (var i = 1; i <= n; i++) {
        if (i % 2 === 0) {
            console.log(i);
        }
    }
}

 

홀수를 구하는 함수

function showOddNumber(n) {
    for (var i = 1; i <= n; i++) {
        if (i % 2 === 1) {
            console.log(i);
        }
    }
}

 

이 두 함수를 보면 i % 2 === [____]   → 이 대괄호 자리에 0 또는 1만 바뀌고 있음

하나의 함수로 만들면 더 효율적인 코드이지 않을까 의문이 발생

 

0 과 1 을 파라미터로 받는 방법이 있음

function showOddOrEvenNumber(n, delimiter) {
    for (var i = 1; i <= n; i++) {
        if (i % 2 === delimiter) {        --------- @@
            console.log(i);
        }
    }
}

 

그런데 3의 배수를 출력하려면?

6의 배수면서 12의 배수가 아닌 것을 출력하려면?

위 코드의 @@에 해당하는 if(조건식) 의 조건식만 변경하면 될 것 같다는 생각이 든다

 

일종의 틀을 함수(미완성)에 만들어 두고
함수를 호출하는 곳에서 조건식을 전달하는 방법이 콜백함수

 

 

콜백의 핵심 : 동작을 파라미터화

  • if문에 들어있는 조건식들만 파라미터로 전달한다면 쉽게 해결되는 문제
  • 단순히 0과 1같은 숫자가 아닌 조건식 자체를 함수에게 전달해줄 수는 없을까?
  • 자바스크립트의 함수는 함수에게 다른 코드를 전달하는 것이 가능
  • 단, 전달할 코드가 함수에 묶여있어야 한다는게 포인트

 

ex)  4의 배수이면서 8의 배수는 아닌 수

조건을 표현해보면     

 i % 4 === 0 && i % 8 !== 0  

 

condition 으로 showNumber 함수에 조건식을 전달

// 콜백을 이용한 솔루션
// 정수 n을 전달하면 1 ~ n까지의 정수를 조건에 맞게 출력
function showNumber(n, condition) {
  const nums = []
  for(let i = 1; i <= n; i++) {
    if(condition(i)) {
      nums.push(i);
    }
  }
  console.log(nums);
}
showNumber(50);

 

 

ex ) 템플릿 함수에 콜백 활용

       레시피 템플릿만 함수에 작성하고 요리법 마다 내용만 바꿔가며 출력

 

ex ) 필터링 함수에 콜백 활용

        급여가 400만원 이상이면서 나이가 30세 이상인 사람만 추출

       서울 살면서 직업이 개발자인 사람만 추출

 

 

콜백 함수의 흐름       

   

            ** 함수 호출하면 리턴 값이 호출한 곳으로 돌아온다는 점을 참고

 

프로그램 실행  (map 함수는 메모리에 저장만 된 상태)

 

(1)  map 함수 호출

(2) user ⇒ user.userName 함수가 map 함수의 매개변수인 callback 자리에 전달

                      *** 어떤 실행도 하지 않은 상태

(1)  map 함수 코드 실행 시작

(1) map 함수 내부의 for문 1회차 시작
          1. (3) callback(user)에서 for문 userList의 첫 번째 user를 인자로 대입 후 호출
          2. 아래의 (2) user ⇒ user.userName 함수로 이동
          3. (2)함수를 실행하여 첫 번째 user의 userName 리턴값 연산

          4. 위의 호출한 곳(3)에 리턴 값인 첫 번째 user의 userName을 대입
          5. 1회차 종료

(1) map 함수 내부의 for문 2회차 시작
          1. (3) callback(user)에서 for문 userList의 두 번째 user를 인자로 대입 후 호출
          2. 아래의 (2) user ⇒ user.userName 함수로 이동
          3. (2)함수를 실행하여 두 번째 user의 userName 리턴값 연산
          4. 위의 호출한 곳(3)에 리턴 값인 두 번째 user의 userName을 대입
          5. 2회차 종료 

… 반복

 

(1)  코드 실행 완료하여 mappedArray 값 리턴 후 map 함수 종료

(1)  map 함수 호출한 자리로 리턴된 mappedArray 값이 전달 되어 const nameList에 저장