JS/JavaScript&TypeScript

JavaScript&TypeScript 11. 함수 ( Function )

shin96bc 2022. 4. 3. 00:11

(1) 힘수 ( function )

     Github: https://github.com/SHIN96BC/JavaScript-TypeScript-Concept-2022/tree/main/11_Function

     1) 함수의 역할
          <1> 코드를 묶는 것
          <2> 어떤 목적의 계산을 수행하는 것
          <3> 필요할 때 호출이라는 과정을 통해서 사용할 수 있다. ( 함수의 이름으로 호출한다. )
          cf) 정리하면 함수란, 어떤 목적의 계산을 통해 결과를 얻을 수 있는 코드의 묶음이라고 할 수 있고, 

              그 계산을 필요할 때 호출이라고 하는 과정을 통해서 수행을 시켜 그 결과를 받아 볼 수 있는 

              문법 요소이다.

     2) 함수의 기능
          <1> return
               1> 계산된 결과값을 호출한 곳에 돌려줄 때 사용한다.
               2> output 에 해당한다.

          <2> 인자( 파라미터 )
               1> 어떠한 계산을 수행할 때 필요한 값을 함수에 보내줄때 사용한다.
               2> input 에 해당한다.
               3> 인자값을 넣어주려면 함수쪽에서도 받을 준비를 해야한다.
               4> 반드시 넣어줄 필요는 없다.

     3) 함수의 종류
          <1> 일반 함수 
               1> 일반 함수는 이름이 있어서, 그 이름으로 호출해서 사용할 수 있다.
               2> 일반함수는 정의'문'이다. '문' 이므로 끝에 세미콜론을 찍지 않는다.
               ex) function myFn(x) {
                        return x + 100;
                   }

          <2> 익명 함수 ( 이름이 없는 함수 )
               1> 익명함수는 이름이 없으면 호출해서 사용할 수 없다. 그렇다면 어떻게 사용해야 할까?
               2> 자바스크립트는 언어 레벨에서 함수를 값으로 취급한다. 즉, 변수에 넣을 수 있다.
               3> 일반 함수와 차이점은 익명 함수는 문이 아니라 '식' 즉, 값이라는 것이다. 

                    값이므로 끝에 세미콜론을 찍어야한다.
               4> 사용법: 
                    1. 변수에 넣어서 사용한다. ( 변수명으로 호출할 수 있다. )
               ex) const myfn2 = function () {
                        return 100;
                   };

          <3> 즉시 실행 함수
               1> 즉시 실행 함수는, 함수가 만들어지자마자 즉시 한번 실행되는 함수이다.
               2> 애플리케이션 내에서 단 한번만 실행가능한 함수이다. 

                     ( 애플리케이션을 처음부터 다시 실행하지 않는한 다시 사용할 수 없다. )
               3> 즉시 실행 함수는 값으로 취급한다.
               4> 함수가 만들어지자마자 호출구문을 만나서 호출되서 함수안에 내용이 실행된후 

                    리턴되는 구조를 가지고있다.
               ex) (function() {
                        console.log('즉시 실행 함수 실행');
                   })();

     4) 함수 호출의 종류
          <1> 함수의 이름이나, 변수명에 괄호를 적어서 호출한다.
               1> 가장 일반적인 호출방법이다. ( 대부분의 경우 이렇게 이름으로 호출한다. )
               ex) mtFn();
               ex) mtFn2();

          <2> call() 라고 하는 함수로 호출
               1> call() 과 apply() 의 공통점
                  일반적인 호출문법과 함수가 호출된다는 건 동일하다.
                  첫번째 인자로 context 객체라는 것을 받는다. ( 넣어줘야한다. )

               2> call() 함수는 두번째 인자부터는 일반 함수를 호출 하듯이 필요한 값을 넣어준다.
                    ex) sum.call(null, 10, 20, 30);

               3> call() 함수는 만약에 인자에 40이라는 값을 추가해야할 때 코드 자체를 바꿔야 하는 

                    상황이 발생한다.

          <3> apply() 라고 하는 함수로 로 호출
               1> apply() 함수는 call() 함수와 달리 두번째 인자부터는 필요한 인자를 배열에 담아서 전달한다.
                    ex) sum.apply(null, [10, 20, 30]);

               2> apply() 는 인자 값을 추가하고 싶을때 배열을 따로 변수에 담아서 그 변수를 인자로 넘겨주면 
                  코드를 변경하지 않아도 된다는 큰 장점을 가지고 있다. ( call() 보다 훨씬 유연하게 사용가능 )
                    ex) const arr = [10, 20, 30, 40, 50];
                        sum.apply(null, arr);

     5) 함수 호출의 특징
          <1> 함수에서 인자값을 하나만 받도록 설정해놔도 호출하는 쪽에서 인자값을 여러개를 넣고 호출해도 

                 호출이 성공한다.
          <2> 물론 인자값을 넣지않고 호출해도 호출이 성공한다.
          <3> 즉, 함수가 정의되어있고, 함수의 이름과 호출방법이 맞다면 무조건 호출이 된다.
          <4> 이런 '가변인자' 라고 하는 특징 때문에 조금 더 유연한 처리가 가능하다.
          <5> 가변인자를 처리하는 방법:
               1> 유사 배열 ( 올드한 방법 )
                    1. 자바스크립트의 함수가 호출될 때 함께 전달되는 배열이다.
                    2. 배열과 유사하지만 정확히는 배열이 아니다 ( 하지만 매우 유사하다 )
                    3. arguments 라고 하는 이름으로 함수 안에서 사용가능하다.
                    4. 유사 배열 안에는 호출당시에 넘겨받은 인자들이 차곡차곡 들어가 있다.
                    5. 즉, 함수의 인자를 사용할 필요가 없어지므로, 인자값을 몇개로 설정했냐에 관계없이 

                        사용가능하다.
                    ex) function sum(a, b, c) {
                             let s = 0;
                             for(let i=0; i< arguments.length; i++) {
                                  s = s + arguments[i];
                             }
                             return s;
                        }
                        const abcSum = sum(10, 20, 30, 40);

                    6. 그러나 이 사용법에는 문제가 있다. 이 함수를 사용자가 봤을 때 함수의 이름과 인자 정보를 

                        알 수 있어야 되는데, 이 함수가 가변 인자를 처리하는지, 가변 인자를 처리하지 않고 인자를 

                        아무것도 받지 않는지를 알수가 없다.
                    7. 함수가 함수 바깥쪽에, 함수의 사용자들한테 함수 사용법과 관련된 정보를 거의 아무것도 

                        주지 않기 때문에 매우 불편하다.

               2> 전개 파라미터 ( Rest Parameter )
                    1. 유사 배열의 함수가 주는 정보의 부족이라는 단점을 해결하기 위해서 나온 스펙이다.
                    ex) function sum(...args) {
                             let s = 0;

                             for(let i=0; i< args.length; i++) {
                                  s = s + args[i];
                             }

                             return s;
                        }
                    2. ... 은 몇개가 올지 모른다 라는 의미로 해석하면 된다.
                    3. 이렇게 써놔도 사실 별 차이 없다고 느껴질 수 있다. 하지만, 이렇게 적어놓으면 함수를 

                        딱 봤을 때 한눈에 가변 인자를 처리하는 함수라고 하는 정보를 사용자 쪽에

                        충분히 전달할 수 있다.
                    4. 암묵적으로 작동되는 arguments 라고 하는 방식과 달리, 함수 시그니처에 명시적으로 

                        등장하는 방식이기 때문에 풍부한 정보를 사용자에게 전달해 줄 수 있다는 장점이 있다.

                    5. 추가적인 기능으로 function sum(a, b, ...args) {} 이런식으로 a 와 b 라는 인자를 설정해두면,
                       const abcSum = sum(10, 20, 30, 40); 이런식으로 호출 했을 때 a 에 10, b 에 20 나머지가 

                       args에 들어가게 되므로 훨씬 더 처리하기가 좋아진다.
                       사용자에게 a 와 b 는 필수 값이고, 그 뒤는 안줘도 되고, 더 많이 줘도 돼. 

                       라고 하는 정보를 전달할 수 있다.

                    6. 가변 인자를 처리할 때는 Rest Parameter 방식을 사용하도록 하자.

     6) 함수의 변형
          <1> 애로우 함수 ( 화살표 함수, 한 줄 함수 ) 
               1> 이름을 줄 수 없는 익명 함수가 기본 값이다. ( 이름을 줄 수가 없다. )
               2> 애로우 함수는 반드시 변수에 넣어줘야 한다.

               ex) const sumV2 = (a, b, ...args) => {
                        let s = 0;

                        for(let i=0; i< args.length; i++) {
                             s = s + args[i];
                        }

                        return s;
                   }

               3> 기본적으로 기존 함수와 99% 동일하다. ( 형태만 다르다. )
               4> 애로우 함수는 코드가 한 줄이고, 그 한줄의 결과를 리턴하는 경우 {} 를 생략할 수 있다. 
                  ( 자연스럽게 return 이라는 문구도 생략된다. )
                    ex) const ten = (x, y) => 100 + x + y;

               5> 애로우 함수는 인자가 하나일때는 () 를 생략할 수 있다.
                  ( 아래는 가장 간단한 애로우 함수이다. )
                    ex) const ten = x => 100 + x;

               6> 코드가 많이 간결해지기 때문에  굉장히 많이 사용하는 문법 요소이다.

          <2> 생성기 함수 ( Generator function )
               1> 생성기 함수는 function 과 함수 이름 사이에 * ( 별표 또는 asterisk 라고 한다. ) 를 붙인다.
                    ex) function* geb() {}

               2> 통상적인 함수의 작동 방식과는 완전히 다르다.

               3> Generator 함수는 최초에 호출하면 함수가 실행되지 않고, 실행 준비 상태로만 만든다. 

                    그리고나서 객체 하나를 반환한다. 그 객체에는 함수가 실행 준비를 마쳤으니, 

                    그 함수를 실행할 도구를 담은 객체를 반환한다.

               4> 그래서 그 반환된 객체를 이용해서 함수를 실행했다가 멈췄다가 할 수 있다.

               5> 호출을 한번하고 여러번 호출을 해서, 그 함수가 종료되지 않았는데 그 함수에 다시 들어갔다가 

                    다시 나오고 또 다시 들어갔다가 다시 나오고 이런 방식의 동작을 할 수 있다.

               6> 첫번째 호출했을 때 반환되는 객체에는 next() 라고 하는 함수가 하나 들어가 있다.
                    next() 를 이용해서 Generator 함수한테 값을 줄 수도 있고, Generator 함수가 돌려준 값을 

                    받을 수도 있다.

               7> Generator 함수의 값을 반환하는 방법은 return 도 있지만 yield 라고 하는 키워드를 

                    사용할 수 있다.

               8> Generator 함수는 마치 핑퐁을 하듯이 사용자와 커뮤니케이션을 할 수 있는 스펙을 

                    가지고 있다.

               ex) function* geb() {
                        yield 10;    ( 실행순서 3)
                        yield 20;    ( 실행순서 5)
                        return 30;   ( 실행순서 7)
                   }

                   const g = gen(); ( 실행순서 1)
                   g.next();  ( 실행순서 2)
                   g.next();  ( 실행순서 4)
                   g.next();  ( 실행순서 6)

          <3> 비동기 함수 ( async 함수 )
               1> 함수 앞에 async 를 붙여준다. 
                    ex) async function myTask() {}

               2> 우리가 비동기 작업을 코드로 구성할 때 'promise' 라고 하는 스펙을 사용하는데, 

                    이 promise의 어려운 비동기 코드 구성을 동기적으로, 즉 일반 함수와 같이 순차적으로

                    코드가 실행되는 방식으로 코드를 작성할 수 있게 만들어주는 스펙이 바로 

                    비동기 함수이다.

               3> 비동기 함수는 'promise' 와 callback 함수의 이해가 없으면 사용할 수가 없다.