즉시 실행 함수

  • 함수 정의와 동시에 즉시 호출되는 함수를 즉시 실행 함수(IFE, Immediately Invoked Function Expression)라고 한다.
    즉시 실행 함수는 단 한번만 호출되며 다시 호출할 수 없다.
  • 즉시 실행 함수는 익명함수를 사용하는 것이 일반적이다.
    (기명 즉시 실행 함수도 사용할 수도 있음)
    기명함수는 함수 선언문이 아니라 함수 리터럴로 평가되며, 함수 이름은 함수몸체에서만 참조할 수 있는 식별자이므로 즉시 실행함수를 다시 호출할 수는 없다.
    // 익명 즉시 실행 함수
    (function() {
        var a = 3;
        var b = 5;
        return a * b;
    }());
      
    // 기명 즉시 실행 함수
    (function() {
        var a = 3;
        var b = 5;
        return a * b;
    }());   
      
    foo();   // ReferenceError: foo is not defined.   
    
  • 즉시 실행 함수는 반드시 그룹 연산자(…)로 감싸야 한다.
  • 즉시 실행 함수도 일반 함수처럼 값을 반환할 수 있고 인수를 전달할 수도 있다.
    var res = (function(a, b) {
      return a * b;
    }(3, 5));   
      
    console.log(res); // 15
    
  • 즉시 실행 함수내에 코드를 모아 두면 변수나 함수의 이름 충돌을 방지할 수 있다.
    모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시실행함수의. 지역변수가 된다.
    이러한 특성을 이용하면 전역변수 사용을 제한할 수 있다.
    이 방법은 라이브러리 등에서 자주 사용된다.
    (function() {
        var foo = 10;    // 즉시 실행함수의 지역 변수
        // ... 
    }());
       
    console.log(foo);     // ReferenceError: foo is not defined. 
    

중첩함수

  • 함수 내부에 정의된 합수를 중첩함수(nested function)또는 내부함수(inner function)라고 한다.
  • 중첩 함수를 포함하는 함수는 외부함수(outer function)라고 부른다.
  • 중첩 함수느 외부 함수 내부에서만 호출가능핟.
    일반적으로 중첩함수는 자신을 포함하는 외부 함수를 돕는 헬퍼 함수(helper function)으 역할을 한다.
    function outer() {
        var x = 1;
          
        // 중첩 함수
        function inner() {
            var y = 2;
            console.log(x + y);  // 3 
        }
        inner();
    }
    outer();      
    
  • ES6부터 함수정의는 문이 위치할 수 있는 문맥이라며 어디서든지 가능하다.
    함수 선언문의 경우 ES6이전에는 코드의 최상위 또느 다른 함수 내부에서만 정의할 수 있었으나 ES6부터는 if문이나 for 문등의 코드 블록내에서도 정의할 수 있다.
    단, 호이스팅으로 인해 혼란이 발생할 수 있으므로 if문이나 for문 등의 코드블록에서 함수 선언문을 통해 함수정의하는것은 바람직하지 않ㄷ.
  • 중첩 함수는 스코프와 클로저와 깊은 관련이 있다.

콜백함수(Callback Function)

  • 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백함수라고 한다.
    매개변수를 통해 함수의 외부에서 콜백함수를 전달받은 함수를 고차함수(Higher-Order Function, HOF) 라고 한다.
    // 외부에서 전달받은 f를 n만큼 반복호출
    function repeat(n, f) {
      for(var i = 0; i < n; i++) {
        f(i);   // i를 전달하면서 f를 호출
      }
    }
      
    var logAll = function(i) {
      console.log(i);
    };
    repeat(5, logAll);  // 0 1 2 3 4 
      
    var logOdds = function(i) {
      if (i % 2) console.log(i);  
    };
    repeat(5, logOdds);  // 1 3
    
  • 매개변수를 통해 함수를 전달받거나 반환값으로 함수를 반환하는 함수를 함수형 프로그래밍 패러다임에서 고차함수라고 한다.
  • 중첩외부함수를 돕는 헬퍼 함수 역할을 하는 것처럼 콜백함수도 고차함수에 전달되어 헬퍼함수 역할을 한다.
    단, 중첩함수는 고정되어 있어 교체하기 곤란하지만, 콜백함수는 함수외부에서 고차함수 내부로 주입하기 때문에 자유롭게 교체할 수 있다는 장점이 있다.
    즉, 고차함수는 콜백함수를 자신의 일부분으로 합성함!!
  • 고차함수는 매개변수를 통해 전달받은 콜백함수의 호출시점을 결정해서 호출한다.
  • 고차함수에 콜백함수를 전달할때 콜백함수를 호출하지 않고 함수 자체를 전달해야 한다.
  • 콜백함수가 고차함수 내부에서만 호출된다면 콜백함수를 익명함수 리터럴로 정의하면서 곧바로 고차함수에 전달하는것이 일반적이다.
    콜백함수로서 전달된 함수리터럴은 고차함수가 호출될때마다 평가되어 함수 객체를 생성한다.
    따라서 콜백함수를 다른곳에서도 호출할 필요가 있거나 콜백함수를 전달받은 함수가 자주 호출된다면 함수 외부에서 콜백함수를 정의한 후 함수참조를 고차함수에 전달하는편이 효율적이다.
    // 익명함수 리터럴을 콜백 함수로 고차함수에 전달한다.  
    // 익명 함수 리터럴은 repeat 함수를 호출할때마다 평가되어 함수 객체를 생성한다.  
    repeat(5, function(i) {
        if (i % 2) console.log(i);  
    });
    
  • 콜백함수는 함수형 프로그래밍 패러다임뿐만 아니라 비동기처리(이벤트 처리, Ajax 통신, 타이머함수 등)에 활용되는 중요한 패턴이다.
  • 콜백함수는 비동기 처리 뿐만 아니라 배열 고차함수에서도 사용된다.
    var res = [1, 2, 3].map(function(item) {
        return item * 2;
    });
    console.log(res);   // [[ 2, 4, 6 ]]
      
    res = [ 1, 2, 3].filter(function(item) {
        return item % 2;
    });
    console.log(res);   // [ 1, 3 ]
      
    res = [ 1, 2, 3].reduce(function(acc, cur) {
      return acc+ cur;
    }, 0);
    console.log(res);  // 6
    

순수함수와 비순수함수

  • 순수함수(pure function) : 외부상태에 의존하지도 않고 변경하지도 않는, 부수효과가 없는 함수
    비순수함수(impure function) : 외부상태에 의존하거나 외부상태를 변경하는, 부수효과가 있는 함수
  • 순수함수는 어떤 외부 상태에 의존하지 않고 오직 매개변수를 통해 함수 내부로 전달된 인수에만 의존해반환값을 만든다.
    (함수의 외부상태에 의존하는 함수는 외부 상태에 따라 반환값이 달라진다.)
    var count = 0; 
      
    function increase(n) {
      return ++n;
    }
    // 순수함수가 반환한 결과값을 변수에 대할당해서 상태를 변경
    count = increase(count);
    console.log(count);    // 1
      
    count = increase(count);
    console.log(count);   // 2
    
  • 비순수함수는 외부 상태에 의존하는데, 순수함수와 달리 외부 상태를 변경하는 부수효과(side effect)가 있다.
    var count = 0;
      
    function increase() {
      return ++count; // 외부상태에 의존하며 외부상태를 변경함
    }
      
    increase();
    console.log(count);  // 1
    increase();
    console.log(count);  // 2
    

    함수 내부에서 외부상태를 직접 참조하지 않더라도 매개변수를 통해 객체를 전달받으면 비순수 함수가 된다.
    함수가 외부상태를 변경하면 상태 변화를 추적하기가 어려워진다.
    따라서 함수 외부 상태 변경을 지양하는 순수함수를 사용하는것이 좋다.

  • 함수형 프로그래밍은 순수함수와 보조함수의 조합을 통해 외부 상태를 변경하는 부수효과를 최소화해서 불변성(immutability)를 지향하는 프로그래밍패러다임이다.
    로직내에 존재하는 반복문과 조건문을 제거해서 복잡성을 해결하며, 변수 사용을 억제하거나 생명주기를 최소화해서 상태변경을 피해 오류를 최소화하는것을 목표로 한다.
    자바스크립트는 멀티패러다임 언어이므로 객체지향 프로그래밍뿐만 아니라 함수형프로그래밍을 적극적으로 활용하고 있음!

참조(모던 자바스크립트 Deep Dive)