IIFE

js에서 자주사용되는 코딩패턴 중 하나이다.

JS에서의 함수

    function foo() {
        alert("Hello World");
    }

    foo();

IIFE를 적용하지 않은 코드

foo 라는 함수를 1-3째 줄에 선언하고 5번째 줄에서 foo();를 통해 호출해내는 일반 개발자들이라면 자연스럽게 떠올릴 만한함수의 선언과 호출 과정이다.

    var msg = "Hello World";
    var foo = function () {
        alert(msg);
    };

    foo();

js의 특징 중 하나인 함수 표현식이다. foo라는 변수에 함수타입의 값을 할당하였다. 이러한 것을 함수 표현식 이라고 한다.

자바스크립트에서의 함수는 다른 값들(변수 등)과 비슷하게 쓰일 수 있다. 변수에 할당도 가능하고 매개변수로도 활용이 가능하고 return값으로도 활용가능하다. 그만큼 이 함수를 잘 사용해야 자바스크립트에서의 효율적인 코딩이 가능한 것이다.

위에서 선언한 함수표현식의 function 구문 뒤에 이름이 붙여져 있지않다. foo같은. 그런 것을 익명함수라고 한다. 반대로 이름이 주어져 있는 경우는 Named function이라고 하며 차이는 재귀적 호출이 가능한가 아닌가가 대표적이다.

예)

    var foo = function poo () {
        poo();
    }

Named function일 경우 저런식으로 함수 내에서 재귀적 호출이 가능하다는 것이다. 저 함수 스코프 밖에서 poo(); 는 호출되지 않는다.

IIFE

    !function () {
        alert("Hello");
    } ();

이 함수의 특징

첫번째 줄의 !이다. 자바스크립트에서는 function이라는 구문을 만나면 함수가 선언될 것이라고 예측한다. 그러한 일이 일어나지 않게 하기위해서(IIFE 방식을 사용하기 위해서) 그 앞에 !을 붙여준다. 이렇게 해주면 자바스크립트는 이 function을 선언문으로 인식하지않고 표현식으로 다루게 된다. (이 밖에도 void + -등도 앞에 붙여 줄 시 표현식으로 인식하게 되어 선언하자마자 바로 사용할 수 있는 환경을 조성 할 수 있다.)

    (function () {
        alert("Blex");
    });

이 방식이 보편적인 IIFE문체이다. 필자가 참고한 글의 저자는 첫번째 방식을 선호한다고 하지만 필자는 두번째 방식을 더 선호하고 실제로 구글에서 예제를 찾아볼 때 두번째 방식을 자주 접해서 두번쨰 방식이 더 익숙하다고 생각한다.

정리하자면 이 IIFE문체는 딱 한번만 쓸 function을 효율적으로 활용하는 디자인 패턴이라고 보면 될 것 같다. 예를 들면 자바스크립트로 게임을 만들 때 game() function이라던가 하는 경우 말이다. (필자가 최근 snake 게임을 만들떄 사용했음.)

IIFE의 활용

IIFE의 특징중 하나가 IIFE 내부에 정의된 변수들은 바깥에선 볼 수 없다는 것이다.

    (function () {
        var foo;
        var poo;

        init();

        function init () {
            foo = 5;
            poo = 10;
        }
    }());

이 함수의 구성에 대해 살펴보면 foo poo라는 두 가지의 변수가 선언되어있고 이 변수를 init () 이라는 내부함수에서 접근하여 값을 할당한다. 요약하자면 내부의 init()이라는 함수 외에는 이 변수에 영향을 줄 수 있는 요인이 없다는 것이고 foopoo는 오염되지 않는다고 볼 수 있다. 이러한 IIFE 패턴의 private한 특성을 이용하여 코드가 길어지고 각종 전역 변수, 함수들이 난무할때 꼭 오염되지 않아야 할 변수들을 지켜낼 수 있다.

값을 return 하는 IIFE

    var foo = (function () {
        return "HI";
    }());

    console.log(foo);

이런식으로 변수return을 담은 IIFE문체를 할당하면 값을 return하는 것이 가능하다.

Parameter가 있는 IIFE

    (finction foo(foo1, foo2) {
        for(var i = 1; i <= times; i ++) {
            console.log(foo1);
        }
    }("Hello!", 5));

마무리

IIFE는 여태까지도 많이 써 왔고 앞으로도 많이 쓸 디자인 패턴이다. IIFE 그 자체에만 집중 할 것이 아닌 return, parameter를 활용한 좀 더 깊은 IIFE의 활용으로 코드를 좀 더 가독성있고 효율적으로 짤 수 있어야 할 것이다.

javascript의 이벤트 루프

자바스크립트가 싱글스레드 이면서 비동기인 이유는 브라우저에 있다. 브라우저의 api를 통해 접근하는 행위가 비동기 행위라고 볼 수 있다.

    function main () {
        console.log('A');
        setTimeout(
        function display() {console.log('B);}
        , 0);
        console.log('C');
    }

    main();
    동작결과
    A
    C
    B

이 함수의 동작과정을 살펴보자

  1. 메인함수에 대한 호출 main()이 stack에 push()된다. 그리고 console.log('A');가 stack에 쌓였다가 곧바로 pop()되어 A가 출력된다.

  2. display()를 가진 setTimeout()가 콜스택으로 push()되고 실행된다. 이 때 setTimeout()은 딜레이를 사용하기위해 브라우저의 API를 사용한다. 그 후 pop()된다.

  3. 브라우저에서 delay에 대한 타이머가 돌아갈때 console.log('C');push()된다.

  4. main()함수의 마지막 statement인 console.log('C')push()된 후 C를 출력한다 그리고 모든 것을 실행시킨 main()pop()된다.

  5. 콜스택이 모두 비워진 후에야 display()가 콜스택에 push()되고 실행된다. 그리고 알파벳 B가 콘솔에 출력된다. 이것이 자바스크립트의 기본적인 이벤트에 대한 루프이다.

그래서 setTimeout()에서의 delay파라미터는 함수가 실행된 후 딜레이를 계산하는것이 아니라 특정 지점(위에서는 main함수가 pop되서 콜스택이 모두 비워진 시점)부터 대기시간을 계산한다고 생각 할 수 있겠습니다.

js의 스케줄 관리

  • setTimeout은 일정 시간 간격 이후에 함수가 한 번 실행된다.
  • setInterval은 일정 시간 간격으로 함수가 주기적으로 실행된다.

setTimeout

    let timerId = setTimeout(func | code, [delay], [arg1], [arg2])

func|code 실행을 위한 함수나 문자열

delay 실행ㅎ아기 전의 딜레이 ms단위로 되어있음

arg1, arg2 function에 대한 인자.

1초 후에 hello를 출력하는 코드

    function foo () {
        console.log("Hello");
    }

    setTimeout(foo, 1000);

func|code라고 기입하여 함수와 문자열이 가능하다고는 써놓았지만 문자열보다는 함수를 권장한다.

함수를 인자로 넘긴다고해서 ()를 뒤에 붙이는 실수는 범하지 마시길 함수의 이름만 넘겨주면 되는것이다.

setInterval

    let timerId = setInterval(func | code, [delay], [arg1], [arg2])

기본적으로 setTimeout()이랑 사용법은 비슷하다. 타임아웃이 일회성이었다면 인터벌은 주어진 delay()의 시간마다 그 행위를 반복하는 것이다.