ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BEB Section 1 - 고차함수
    2nd of BEB/Codestates 2021. 11. 25. 02:15

     Javascript에서는 함수를 아래와 같이 취급한다.

     

    1. 변수에 할당 가능하다.
    2. 다른 함수의 인자로 전달될 수 있다.
    3. 다른 함수의 결과로서 리턴 가능하다.

     

     사실 난 아직도 얘네들이 매우 헷갈린다. 함수 안에 함수가 선언된다는 것 자체가 약간 내 머리 속에서는 이게 말이 되는거냐? 하고 박혀 있었는데 그 틀을 깨버린 Javascript..

     

     일단 함수를 변수에 할당할 수 있기 때문에, 배열의 요소나 객체의 속성값으로도 저장할 수 있다. -> 사실 이거 무슨 말인지 모르겠어서 뒤에 말을 읽어봤는데

     

    Data type 다루 듯 다룰 수 있다.

     

    라는 말을 듣고 곧바로 이해.

     

     본격적으로 들어가기 전에 다들 호이호이 하시길래 이게 뭔 말이야 했는데, 호이스팅(Hoisting)이었다.

    • 호이스팅은 선언된 위치 상관없이 어디서든 함수 사용 가능
    • 코드 실행 과정에서 함수 선언부를 코드 최상단으로 끌어올리는 것처럼 보이게 한다.

    하지만 호이스팅에 의존하다보면 코드 유지 보수에 어려움이 있고, 디버깅 시 코드의 가독성이 매우 떨어진다.

     

    const square = function (num){
      return num * num;
    };
    
    let output = square(7);
    console.log(output); // 49

     

     고차 함수

     고차함수는 함수를 인자로 받을 수 있고, 그 형태를 그대로 리턴할 수 있는 함수이다. 맨 위에 Javascript의 함수 개념에 대해 간단히 설명했는데, 한 가지 더 말해주자면 변수를 따로 할당하지 않고 함수를 바로 사용할 수 있다. 다 그대로인데, 변수가 빠지고 고대로 동작한다는 뜻. 고차함수는 또한 커리 함수라고도 불린다.

     여기서 콜백 함수가 쓰이게 되는데, 콜백 함수는 어떤 이벤트가 발생했거나 특정 지점에 도달했을 때 시스템이 호출되는 함수를 말한다. 일단 어떤 작업 하나가 완료가 돼야 호출되는 경우가 다분하다.

     

    (여기서부턴 저만의 설명 방법입니다!)

     

     

      • 다른 함수를 인자로 받는 경우
    function double(num){
      return num * 2;
    }
    
    function doubleNum(func, num){
      return func(num);
    }
    
    let output = doubleNum(double, 4);
    console.log(output); // 8

     

     일단 함수가 2개 만들어졌고, doubleNum 함수에 func 콜백 함수가 선언되었다. 근데 doubleNum의 return 값을 보면 위에 double 함수랑 비슷한 형태다. 이렇게 우리는 double 함수는 doubleNum의 콜백 함수임을 알 수 있다.

     

     

    • 함수를 리턴하는 경우
    function adder(added){
      return function(num){
        return num + added;
      };
    }
    
    let output = adder(5)(3);
    console.log(adder); // 8
    
    const add3 = adder(3);
    let output = add3(2);
    console.log(output); // 5

    생각할 때 그림을 오지게 그리는 편

     adder 라는 함수 안에 또 함수가 호출되었는데 얘는 또 특이하게 이름 없이 그냥 return 값으로만 주었다. 난 로직을 이렇게 생각해냈다.

     일단 adder 함수 안에 함수가 return된 건데 난 이걸 무시하고 일단 위 그림대로 이해했다. adder 안에는 num과 added가 있으니까 그 안에서 자기들끼리 노는데 안에 숫자의 순서만 잘 맞춰주자는 생각이었다. adder(5)(3)이 그 예시이다. adder의 5는 added의 값이다. 3은 num의 값이고, 하고 순서를 맞췄다. add3 같은 경우는 일단 adder(3)이니까 added에 3이 들어가겠다는 생각을 바로 했고, 그 다음 전달받은 값은 add3에 넣어주었다.

     

     

    • 함수를 인자로 받고 함수를 리턴하는 경우
    function double(num) {
      return num * 2;
    }
    
    function doubleAdder(added, func) {
      const doubled = func(added);
      return function (num) {
        return num + doubled;
      };
    }
    
    doubleAdder(5, double)(3); // 13
    const addTwice3 = doubleAdder(3, double);
    addTwice3(2); // 8

    이해하기 개어려움.

     이건 머리로 그림 그리다가 결국 애매하게 그림으로 표현해봤다. return 되는 값은 결국 num + doubled 이다. 근데 얘가 무조건 added라는 뜻은 아니고 임의로 그렇게 둔다는 뜻이다. 위에 doubleAdder 함수 때문이다. 그래서 밑에 doubleAdder(5, double)(3); 이걸 보면 added에 num을 대입한다. (콜백함수니까) 그럼 일단 5의 값을 저장하고 뒤에 double 함수로 다시 돌아가서 실행해야 하니까 받아온 5의 값을 2와 곱해준다. 일단 10의 값을 받아왔고 다시 doubleAdder 함수로 와 더하기 연산을 다시 진행한다. (10)(3)의 계산이니까 답은 13이 나온다.

     

     고차함수에는 또 그 안에 쓸 수 있는 내장함수가 있다. 대표적으로 map, filter, reduce 가 있다. 

     

     

    • map

     모든 요소에게 동일한 행동을 준 값에 대해 모두 반환하고, 기존에 있던 배열은 수정하지 않는다.

     

    let arr = [1, 2, 3];
    
    let result = arr.map(function(el) {
      return el * 2;
    });
    
    console.log(result);

     

     arr 배열에 1, 2, 3이 순서대로 들어가 el에 순차적으로 들어간다. 그리고 각 숫자는 2씩 곱해져 다시 반환되고, 결과값이 [2, 4, 6] 으로 나오게 된다.

     

     

    • filter

     모든 요소 중 원하는 값만 필터링한 후 반환된다. 이 또한 기존에 있던 배열은 수정하지 않는다. 

     

    let arr = [1, 2, 3];
    
    let result = arr.filter(function(el) {
      return el % 2 !==0
    });
    
    console.log(result);

     

     arr 배열에 1, 2, 3이 순서대로 들어가 el에 순차적으로 들어간다. 각 숫자는 return 문에 있는 조건 하에 true인 요소들만 뽑아 result로 나온다. 

     

    • reduce

     배열을 하나의 값으로 만들어준다. 초기값을 정할 수 있고, 정해진 값이 없다면 배열의 맨 첫 번째 요소가 초기값이 된다. 초기값은 누적값의 기반이 된다.

     

    let arr = [1, 2, 3];
    
    let result = arr.reduce(function(acc, cur, idx) {
      acc + cur;
      return acc;
    });
    
    console.log(result);

     

     초기값이 정해진 게 없기 때문에 1이 초기값이 된다.  그럼 acc에 1이 들어가고 그 다음 2를 이제 넣는 차례가 된다. 2는 cur 자리에 들어가게 되고 아까 acc에 1이 들어간 변수와 더해져서 누적값은 3이 된다. 아까 초기값은 누적값의 기반이 된다고 그랬으니 acc의 값은 3으로 변경된다.

Designed by Tistory.