[자바스크립트]

[JavaScript/DeepDive]12.함수(3)

ki7348 2021. 5. 14. 10:59
  • [12.7] 다양한 함수의 형태
  • 즉시 실행 함수
  • 함수 정의와 동시에 즉시 호출되는 함수를 즉시 실행 함수라고 한다.
    • 즉시 실행 함수는 단 한번만 호출되며 다시 호출할 수 없다.
      • ( function ( ) {
             var a = 3;
             var b = 5;
             return a * b;
        } ( ) );
    • 즉시 실행 함수는 함수 이름이 없는 익명 함수를 사용하는 것이 일반적이다.
      • 함수 이름이 있는 기명 즉시 실행 함수도 사용할 수 있다.
        • 하지만 그룹 연산자 ( ... ) 내의 기명 함수는 함수 선언문이 아니라 함수 리터럴로 평가되며 함수 이름은 함수 몸체에서만 참조할 수 있는 식별자이므로 즉시 실행 함수를 다시 호출할 수는 없다.
    • 즉시 실행 함수는 반드시 그룹 연산자 ( ... )로 감싸야 한다.
    • 즉시 실행 함수도 일반 함수처럼 값을 반환할 수 있고 인수를 전달할 수도 있다.
      • var res = (function ( ) {
             var a = 3;
             var b = 5;
             return a * b;
        }( ));
        // 즉시 실행 함수도 일반 함수처럼 값을 반환할 수 있다.

        console.log(res); // 15

        res = (function(a, b){
             return a * b;
        }(3, 5));
        // 즉시 실행 함수에도 일반 함수처럼 인수를 전달할 수 있다.

        console.log(res); // 15
      • 즉시 실행 함수 내에 코드를 모아두면 혹시 있을 수도 있는 변수나 함수 이름의 충돌을 방지할 수 있다.
  • 재귀함수
  • 함수가 자기 자신을 호출하는 것을 재귀 호출이라 한다.
    • 재귀 함수는 자기 자신을 호출하는 행위, 즉 재귀 호출을 수행하는 함수를 말한다.
      • 재귀 함수는 반복되는 처리를 위해 사용한다.
        • 이처럼 자기 자신을 호출하는 재귀 함수를 사용하면 반복되는 처리를 반복문 없이 구현할 수 있다.
  • 함수 이름은 함수 몸체 내부에서만 유효하다.
    • 따라서 함수 내부에서는 함수 이름을 사용해 자기 자신을 호출할 수 있다.
  • 함수 표현식으로 정의한 함수 내부에서는 함수 이름은 물론 함수를 가리키는 식별자로도 자기 자신을 재귀 호출할 수 있다.
    • 단, 함수 외부에서 함수를 호출할 때는 반드시 함수를 가리키는 식별자로 해야 한다.
  • 재귀 함수 내에는 재귀 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 한다.
  • 중첩 함수
  • 함수 내부에 정의된 함수를 중첩 함수 또는 내부 함수라 한다.
    • 중첩 함수를 포함하는 함수는 외부 함수라 한다.
      • 중첩 함수는 외부 함수 내부에서만 호출할 수 있다.
        • function outer( ) {
               var x = 1;
               function inner( ) {
                     var y = 2;
                     // 외부 함수의 변수를 참조할 수 있다.
                    console.log(x + y); // 3
               }
               // 중첩 함수

          inner( );
          }

          outer( );
  • 콜백함수
  • 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 하며, 매개 변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차 함수라고 한다.
  • 콜백 함수는 함수 외부에서 고차 함수 내부로 주입하기 때문에 자유롭게 교체할 수 있다는 장점이 있다.
    • 즉, 고차 함수는 콜백 함수를 자신의 일부분으로 합성한다.
    • 고차 함수는 매개변수를 통해 전달받은 콜백 함수의 호출 시점을 결정해서 호출한다.
      • 콜백 함수는 고차 함수에 의해 호출되며 이때 고차 함수는 필요에 따라 콜백 함수에 인수를 전달할 수 있다.
        • 따라서 고차 함수에 콜백 함수를 전달할 때 콜백 함수를 호출하지 않고 함수 자체를 전달해야 한다.
          • 콜백 함수가 고차 함수 내부에만 호출된다면 콜백 함수를 익명 함수 리터럴로 정의하면서 곧바로 고차 함수에 전달하는 것이 일반적이다.
            • repeat(5, function ( i ) {
                   if (i % 2) console.log( i );
              }); // 1 3
              // 익명 함수 리터럴을 콜백 함수로 고차 함수에 전달한다.
              // 익명 함수 리터럴은 repeat 함수를 호출할 때마다 평가되어 함수 객체를 생성한다.
          • 콜백 함수를 전달받는 함수가 자주 호출된다면 함수 외부에서 콜백 함수를 정의한 후 함수 참조를 고차 함수에 전달하는 편이 효율적이다.
            • var logOdds = function( i ) {
                   if (i % 2) console.log( i );
              };
              // logOdds 함수는 단 한 번만 생성된다.
              repeat(5, logOdds);  // 1 3
              //고차 함수에 함수 참조를 전달한다.
            • 콜백 함수를 익명 리터럴로 정의하면서 곧바로 고차 함수에 전달하면 고차 함수가 호출될 때마다 콜백 함수가 생성된다.
  • 순수 함수와 비순수 함수
  • 함수형 프로그램이에서는 어떤 외부 상태에 의존하지도 않고 변경하지도 않는, 즉 부수 효과가 없는 함수를 순수 함수라고 하고, 외부 상태에 의존하거나 외부 상태를 변경하는, 즉 부수 효과가 있는 함수를 비순수 함수라고 한다.
  • 순수 함수는 동일한 인수가 전달되면 언제나 동일한 값을 반환하는 함수다.
    • 즉, 순수 함수는 어떤 외부 상태에도 의존하지 않고 오직 매개변수를 통해 함수 내부로 전달된 인수에게만 의존해 반환값을 만든다.
      • 순수 함수는 어떤 외부 상태에도 의존하지 않으며 외부 상태를 변경하지도 않는 함수다.
        • var count = 0; // 현재 카운트를 나타내는 상태
          function increase(n) {
               return ++n;
          }
          // 순수 함수 increase는 동일한 인수가 전달되면 언제나 동일한 값을 반환한다.
          count = increase(count);
          // 순수 함수가 반환한 결과값을 변수에 재할당해서 상태를 변경
          console.log(count); // 1
          count = increase(count);
          console.log(count); // 2
  • 반대로 함수의 외부 상태에 따라 반환값이 달라지는 함수, 다시 말해 외부 상태에 의존하는 함수를 비순수 함수라고 한다.
    • 비순수 함수의 또 하나 특징은 순수 함수와는 달리 함수의 외부 상태를 변경하는 부수 효과가 있다.
      • 즉, 비순수 함수는 외부 상태에 의존하거나 외부 상태를 변경하는 함수다.
        • var count = 0; // 현재 카운트를 나타내는 상태: increase 함수에 의해 변화한다.
          function increase( ) {
               return ++count; // 외부 상태에 의존하며 외부 상태를 변경한다.

          // 비순수 함수
          increase( ); // 비순수 함수는 외부 상태(count)를 변경하므로 상태 변화를 추적하기 어려워진다.
          console.log(count); // 1
          increase( );
          console.log(count); // 2
  • 함수 내부에서 외부 상태를 직접 참조하지 않더라고 매개변수를 통해 객체를 전달받으면 비순수 함수가 된다.