즉시실행함수 = IIFE?

y0ung·2020년 12월 16일
0

자바스크립트 함수와 자주 사용되는 코딩 패턴중 하나는 Immediately-invoked Function Expression 즉, 즉시실행 함수가 있다. IIFE라고 알려져 있고 "iffy"처럼 발음한다.

자연스러운 함수 정의

함수를 다루는 기본적인 문법

function sayHi() {
  alert("hello, world")
}

sayHi()

이런식으로 함수를 생성하는 방식은 "a function definition" 또는 "a function declaration" 또는 "a function statement"로 불린다.

함수의 정의는 항상 function 키워드로 시작한다. 그리고 뒤에는 함수의 이름이 따라온다. 함수의 이름을 생략하면 문법에 어긋나기 때문에 이름을 생략할수는 없다.

함수 표현식

let msg = "hello, world";
let sayHi = function() {
  alert(msg)
}

sayHi() // "hello, world"를 alert메세지에 띄운다.

sayHi변수를 선언하고 function타입의 값을 할당한다.

할당의 오른쪽에 있는 함수는 주로 "함수 표현식(Function Expression)"이라 한다.대부분의 콜백은 함수 표현식 이다.

익명 함수 표현식

let sayHi = function() {//...}

위의 예제와 같이 function키워드 뒤에 이름이 붙지 않는 함수를 익명함수라고 한다.

이름붙은(Named) 함수 표현식

함수 표현식은 이름을 가질수 있다. 가장 많이 사용되는 형식은 재귀 이다.

let fibo = function fibonacci() {
  // 여기서 fibonacci 함수를 호출할 수 있다.
  // 이 함수 표현식이 이름을 갖고 있기 때문
}

// 여기서 fibonacci()를 호출하면 실패한다. 하지만 fibo()는 동작한다.

익명함수와의 차이점은 함수 자체가 이름을 가지고 있다는 것이다. 이름을 가졌기에 함수내부에서 자신을 재귀적으로 호출할수 있다.

IFFE란?

!,+, -, ~ 등의 1진 연산자

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

이 함수는 생명을 갖자마자 바로 죽어 버린다.

함수의 문장은 언제나 function 이라는 키워드로 시작한다. 자바스크립트가 유효한 문장에서 첫단어로 function 키워드를 볼때 마다, 함수 정의가 일어날 것이라 예측한다. 그래서 이러한 일이 일어나지 않도록 하기 위해서, 첫번째 줄 function 키워드 앞에 !를 붙여주므로서 !뒤에 온것이 무엇이든지 표현식으로 다루게 된다.

void

void function () {
  alert("Hello from IIFE!!")
}();

void는 강제로 함수를 식으로 다뤄지게 한다.

IIFE에서 반환 값이 필요 없을 때, 위의 모든 패턴들은 실용적이다.

클래식한 IIFE 스타일

// 1
(function () {
  alert("I am an IIFE!");
}());

// 2
(function () {
  alert("I am an IIFE, too!");
})();

위의 두가지 문체가 널리 사용되는데, 문체작동 방식이 약간다르다.

// 유효한 IIFE
(function initGameIIFE() {
  // All your magical code to initialize the game!
}());

// 유효하지 않은 IIFE
function nonWorkingIIFE() {
  // 이제 왜 앞뒤로 괄호가 필요한지 알게 될 것이다.
  // 괄호 없이는 그냥 함수 정의입니다. 표현식이 아니다.
  // 문법 에러가 난다.
}();

function () {
    // 여기서도 문법 에러가 난다.
}();

IIFE를 구성하기 위해서는 함수 표현식이 필요하다. 함수 statement이나 정의는 IIFE를 만드는데 절대 이용될 수 없다.

IIFE와 private변수

IIFE 내부에서 정의된 어떤 변수라도 바깥 세상에서는 안보인다.

(function IIFE_initGame() {
  // IIFE 밖에서는 접근할 수 없는 Private 변수
  let lives;
  let weapons;
  
  init();
  
  // IIFE 밖에서는 접근할 수 없는 Private 함수
  function init() {
    lives = 5;
    weapons = 10;
  }
}());

코드 바깥에서는 사용하지 않는 많은 변수와 함수를 전역에 만들 때 마다, 변수와 함수들 모두를 IIFE로 감싸면 좋다. 코드는 계속 동작하지만 전역 스코프를 오염시키지 않기 때문이다. 다른이의 실수 혹은 의도적으로 수정하는 행위를 막을수 있다.

값을 리턴 하는 IIFE

let result = (function () {
  return "From IIFE";
}());

alert(result); // From IIFE

기본적으로 IIFE는 즉시 실행되는데 반환 값은 result변수에 할당된다.

파라미터가 있는 IIFE

IFFE는 호출될 때 인자를 받을수 있다.

(function IIFE(msg, times) {
  for (let i=1; i<=times; i++){
    console.log(msg);  
  }
}("Hello!", 5));

자바스크립트는 항상 현재 함수의 스코프부터 식별자(ID)를 찾을 때까지 계속 더 높은 레벨의 스코프로 올라가며 식별자를 찾는다.

클래식한 자바스크립트 모듈 패턴

let Sequence = (function sequenceIIFE() {
  // 현재 counter 값을 저장하기 위한 Private 변수
  let current = 0;
  
  // IIFE에서 반환되는 객체
  return {
    getCurrentValue: function() {
      return current;  
    },
    
    getNextValue: function() {
      current = current + 1;
      return current;
    }
  };
  
}());

alert(typeof Sequence); // alert("Object");

console.log(Sequence.getNextValue()); // 1
console.log(Sequence.getNextValue()); // 2
console.log(Sequence.getCurrentValue()); // 2

괄호를 생략할 때

함수 표현식에서 앞뒤에 괄호를 해주는 이유는 기본적으로 함수가 statement의 형태가 아닌 expression의 형태가 되도록 만들어 주기 위함이다.

하지만 코드가 명확히 함수 표현식이라면, 괄호를 사용하지 않아도 된다.

let result = function() {
  return "From IIFE!";
}();

참고

profile
어제보다는 오늘 더 나은

0개의 댓글