[22-06-01 바코 프렙 TIL] Recursion, Call Stack,고차함수, reduce, map

Jessie H·2022년 6월 1일
0

바닐라코딩 프렙

목록 보기
2/6
post-thumbnail

png created by here

[ Today's Point ]


💡 Recursion 재귀

💡 call Stack 콜스택

💡 Higher Order Function 고차함수

💡 First-class citizen 일급 객체

💡 reduce

💡 map



Recursion 재귀

어떤 것을 정의할 때 자기 자신을 참조하는 것

Recursion Function 재귀함수

함수 실행 시 자기 자신을 다시 호출해서 코드 진행하는 함수

재귀함수로 팩토리얼 만들기

팩토리얼은 재귀함수의 대표적인 예시인데 나는 그것도 모르고 reduce를 사용해서 풀었다^ㅠ^
다른 분의 블로그에서 재귀함수 설명보다가 알게 되었다....
이불킥 감이므로 스스로 더 부끄러워하기 위해 박제ㄱㄱㄱ

<script>
  //내가 reduce 사용해서 푼 방법
  function factorial(num) {
    if (num === 0) {
      return 0;
    }
    if (num === 1) {
      return 1;
    }
    let arr = [];
    function makenArr(n) {
      for (let i = 1; i < n + 1; i++) {
        arr.push(i);
      }
      return arr;
    }
    return makenArr(num).reduce((누적값, 배열요소) => 누적값 * 배열요소);
  }

  console.log(factorial(3)); // 3*2*1 = 6
</script>

안되는 건 아니지만 코드가 길어서 비효율적이라는 걸 재귀함수 정리하면서 이해했다...
재귀함수 퀴즈면 재귀함수를 사용하는 법을 익힙시다...ㅎㅎㅎ

<script>
 //재귀함수로 팩토리얼 만드는 법
 function factorial(num){
   if(num === 0){ //num이 0이면 바로 0 반환
     return 0;
   }
   if(num === 1){ //num이 1이면 바로 1 반환
     return 1;
   }
   return num * factorial(num -1);
 }
 
 console.log(factorial(3)); //6
</script>

재귀함수 factorial()가 실행되는 과정(단순화함)

- 구해야하는 것: console.log(factorial(3)) 

- 실행 위해 function factorial(num){}안으로 들어감
- if(num === 0){} 읽고 n !== 0 이므로 PASS
- if(num === 1){} 읽고 n !== 1 이므로 PASS
- return num * factorial(num-1) 읽음, 3 * factorial(2) 반환됨
- 현재 구해야하는 것: console.log(factorial(3)) → console.log(3 * factorial(2))

- factorial(2)를 실행하기 위해 function factorial(num){}으로 들어감
- if(num === 0){} 읽고 n !== 0 이므로 PASS
- if(num === 1){} 읽고 n !== 1 이므로 PASS
- return num * factorial(num-1) 읽음, 2 * factorial(1) 반환됨
- 현재 상황: 
  console.log(factorial(3)) → console.log(3 * factorial(2)) → console.log(3 * 2 * factorial(1))
  
- factorial(1) 실행 위해 function factorial(num){}으로 들어감
- if(num === 1){} 읽고 n === 1 이므로 factorial(1)에 1 대입
- 현재 상황: 
console.log(factorial(3)) 
→ console.log(3 * factorial(2)) 
→ console.log(3 * 2 * factorial(1)) 
→ console.log(3 * 2 * 1) = console.log(6); // 6



Call Stack

  • 자바스크립트의 특징으로 여러 함수를 호출할 때 현재 동작 중인 함수와 그 함수 내에서 호출되는 함수, 다음에 호출할 함수 등을 나타내는 것

  • 내가 생각하는 적절한 비유는 프링글스칩!!

  • 프링글스칩 과자통: call Stack, 그 안에 들어있는 감자칩: function stack

    사진출처: http://www.tcpschool.com/c/c_memory_stackframe

  • 먼저 실행된 함수가 아래에 쌓이고 나중에 실행된 함수가 위에 쌓이며, 실행이 끝나면 위에서부터 차례로 stack에서 제거됨

  • call stack이 너무 많이 쌓이면 과부하가 일어난다.

  • 따라서, recursion functions를 너무 많이 쓰면 call stack 과부하가 걸릴 수 있으므로 주의!!


call stack 예시로 보기

아까 만든 factorial()을 통해 call stack이 쌓이는 과정을 녹화해보았다.
(Call Stack 부분과 Scope 부분을 유심히 볼 것!!)

call stack부분을 그림으로 나타내면

*** (anonymous) : 코드를 실행하면 기본적으로 깔리는 Stack이다.

  1. 기본 Stack (anonymous) 가 가장 아래에 쌓임
  2. console.log(factorial(3))실행을 위해 factorial stack이 그 위에 쌓임
  3. factorial(){} 에서 num = 3이므로 3 * factorial(2)을 실행한다.

  1. factorial(2) 값을 알아내기 위해 또 다른 factorial stack이 그 위에 쌓인다.
    (이것이 바로 재귀함수!!)
    ** '두번째 factorial stack'은 factorial(3)을 구하기 위해 읽고, '세번째 factorial stack'은 factorial(2)을 구하기 위해 읽기 때문에 이 두개의 stack은 같지 않고 다른 것!!

  2. factorial(){} 에서 num = 2이므로 2 * factorial(1)을 실행한다.


6. factorial(1) 읽기를 위해 factorial(){}을 읽는다.
7. num =1, return 1; 이므로 factorial(1) = 1이다.

  1. factorial(1)을 구했으므로 세번째에 있는 factorial stack 은 제거된다.

  2. 따라서 factorial(2) = 2 * factorial(1) = 2 * 1 = 2가 된다.

  1. factorial(2)를 구했으므로 두번째에 있는 factorial stack은 제거된다.
  2. factorial(3) = 3 * factorial(2) = 3 * 2 = 6
  3. factorial(3)을 구했으므로 남아있던 factorial stack도 제거된다.
  4. 코드 실행이 종료되면서 (anonymous) stack도 제거된다.



Higher Order Function 고차함수

- 함수를 인자(argument, 함수를 호출할 때 전달되는 실제 값)로 받거나 함수를 반환하는 함수
- 함수를 일급객체로 취급하는 함수

고차함수 예시

<script>
  function a(x){
      return function (){};
  }

  a(function ex(a){
      console.log(a);
  });
</script>

❓ 매개변수(parameter)와 전달인자(argument)

  • 매개변수: 함수의 정의부분에 나열되어 있는 변수, variables
  • 전달인자: 함수를 호출할 때 전달되는 실제 값, value

매개변수, 전달인자 자료출처: https://wayhome25.github.io/etc/2017/12/31/parameter-argument/



❓ First-class citizen(object) 일급 객체

- 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체 

- 인자로 넘기기, 수정하기, 변수에 대입하기와 같은 연산을 지원하고 반환 값으로 사용될 수 있을 때 일급 객체라고 한다.

(출처: 위키백과)

💛 자바스크립트에서 함수는 일급 객체이다.



reduce

적용할배열.reduce(콜백함수[, 초기값]);//초기값은 선택사항

//더 풀어서 쓰면
적용할배열.reduce((누적값, 배열내데이터) => 연산식)

아까 팩토리얼 풀 때 reduce 문법이 헷갈렸기 때문에 다시 정리!!!

reduce는 배열 안에 있는 각각의 데이터를 하나씩 꺼내서 연산을 하고 하나의 누적 연산값을 반환한다.
보통 배열 안의 데이터로 사칙연산할 때 많이 쓴다.

아까 팩토리얼에서 쓴 reduce를 다시 가져와보면

<script>
  function factorial(num) {
      if (num === 0) {
        return 0;
      }
      if (num === 1) {
        return 1;
      }
      let arr = [];
      function makenArr(n) {
         for (let i = 1; i < n + 1; i++) {
           arr.push(i);
         }
         return arr;
      }
      return makenArr(num).reduce((누적값, 배열요소) => 누적값 * 배열요소);
  }
  
  console.log(factorial(3));
</script>

num = 3이므로 arr = [1,2,3]이다.
arr과 reduce만 따로 가져와서 다시 보면

<script>
  makenArr(3) = [1,2,3]
  makenArr(3).reduce((누적값, 배열요소) => 누적값 * 배열요소);

  //1 * 2 = 2(누적값)
  //2(누적값) * 3(다음 배열요소) = 6 
</script>

map

배열의 모든 값을 순환 후 새로운 배열을 반환하기 위해 사용

배열.map(callback(current value, index, source), this)

- current value : 현재 반환할 값
- index: 현재 해당하는 인덱스의 값
- source: 순회하는 대상 객체
- this: 사용할 this 키워드의 값
  * this 변경시에는 화살표 함수로 표시 불가능
let arr = [1,2,3]

let result = arr.map((num) => num + 1);
console.log(result);//[2,3,4]






<문법 자료 출처>

profile
코딩 공부 기록장

0개의 댓글