IIFE(Immediately Invoked Function Expressions) 란?

Dean H. Park·2020년 8월 18일
2

JS

목록 보기
4/8
post-thumbnail

잠깐! 🙌🏻

함수 선언식과 함수 표현식 (관련 문서)

함수 선언식(또는 함수문)에는 function 문, 함수명 및 함수 본문이 필요하다. 자바스크립트 파일(또는 자바스크립트가 포함된 HTML 문서)이 로드되면 코드가 실행되기 전에 함수 선언식이 코드의 맨 위로 올라간다.

function doSomething(){
  // Function contents
};

표현식은 값으로 인식되는 코드 단위이다. 함수 선언식과 함수 표현식의 주요 차이점은 함수 선언식을 사용할 때 이름을 생략하여 익명 함수를 만들 수 있는 것이다. 또한 함수 표현식은 호이스팅(호이스팅 이란?)되지 않는다. 자바스크립트 인터프리터가 해당 스크립트에 도달 할 때까지 로드되지 않는다. 그 시점 이전에 함수를 호출하려고하면 오류가 발생한다.


IIFE(Immediately Invoked Function Expressions) 란?

IIFE(즉시 호출 함수 표현식)은 주로 이름 충돌 최소화 및 private 변수 생성에 사용되는 자바스크립트 디자인 패턴 이다.

IIFE의 일반적인 형식은 전체 함수를 그룹화하는 연산자(괄호 집합)로 묶고 익명 상태로 두는 것이다. 끝에있는 추가 괄호()가 즉시 호출한다.

(function() {
    // 함수 내용
})();

IIFE를 변수에 저장할 수있는 이유는 함수 표현식이 값을 반환하기 때문이다.

IIFE의 이름 충돌 최소화

이름 충돌 가능성을 줄이기 위해 전역 네임 스페이스 (전역 범위에 명명 된 변수/함수 포함)의 오염을 최소화하는 것이 좋다.

함수 내부에 변수를 정의하면 전역 네임 스페이스에 접근 할 수 없게된다.

function exampleFunction() {
  let foo = 'bar';

  console.log(foo); // bar
}

exampleFunction();

console.log(foo); // ReferenceError: foo is not defined

즉, IIFE를 사용하면 익명 함수를 사용하고 두 번 이상 반환 될 가능성을 제거 할 수 있다.

(function() {
  let foo = 'bar';

  console.log(foo); // bar
})();

console.log(foo); // ReferenceError: foo is not defined

함수 표현식은 함수 선언식과 달리 값으로 평가되기에 IIFE를 변수에 저장할 수 있다.

const result = (function() { 
  const name = '뷔탈릭'; 
  return name; 
})(); 

result; // "뷔탈릭"

IIFE 괄호 생략

IIFE를 변수에 할당하는 경우 둘러싸는 괄호를 생략 할 수 있다.

const example = function() {
  alert('IIFE 성공!');
}();
// "IIFE 성공!"

IIFE를 변수에 할당하지 않으면 반드시 괄호로 묶어야 한다. 안그러면 자바스크립트 인터프리터가 함수문에 도착하자마자 함수 선언식으로 인지한다.

function() {
  alert('IIFE 성공!'); // 동작 안함
}();
// SyntaxError: function statement requires a name

만약 괄호를 사용하지 않으려면 느낌표를 함수 앞에 추가하여 인터프리터가 다음을 표현식으로 인지하게 할수 있다.

!function() {
  alert('IIFE 성공!');
}();
// "IIFE 성공!"

그 외 방법도 있다.

~function () { /* ... */ }();
-function () { /* ... */ }();
+function () { /* ... */ }();
void function () { /* ... */ }();

IIFE 대체 구문

IIFE 포맷은 두 가지가 있으며, 성능적인 차이는 없다.

(function() {
    // 함수 내용
})();

(function() {
   // 함수 내용
}());

IIFE는 꼭 익명이어야 하는가?

IIFE는 반드시 익명이 아니어도 된다.

(function namedIsFine() {
  alert('IIFE에 이름 붙이기 성공!');
})();

IIFE와 클로저(관련 문서)

IIFE 내부에 클로저를 활용할 수 있다.

아래는 일반 함수에서 클로저를 활용한 예이다.

function makeCounter() {
 let count = 0;
 return function() {
   ++count;
   return count; 
 };
};

console.log(makeCounter()()); // 1
console.log(makeCounter()()); // 1

let counter = makeCounter();

console.log(counter()); // 1
console.log(counter()); // 2

아래는 IIFE에 클로저를 활용한 예이다.

let countingFunction = (function() {
  let count = 0;
  return function() {
    ++count;
    return `count equals ${count}`; 
  };
})();
console.log(countingFunction()); // 1
console.log(countingFunction()); // 2

위 예제들의 count 값은 전역 접근이 안되는 private이다.

각 예제는 후속 함수 호출에서 count 값을 보존하는 이점이 있다. 클로저가 사용되지 않은 경우, count는 각 함수 호출마다 0으로 리셋될 것이다.

첫 번째 (IIFE가 아닌 함수) 예제는 클로저를 호출하여 원할 때마다 재설정 할 수 있고, 두 번째 예제는 전체 함수가 한번 실행되면 리셋되지 않는다.

IIFE를 사용한 클로저의 이점은 이름 지정이 필요없다는 것이다(대신 변수에 할당 필요). 또는 이름을 지정하면, 전역 범위에 표시되지 않으므로 전역 네임 스페이스를 오염시키는 항목 하나를 줄일 수 있다.

클로저를 포함한 IIFE의 다른 예를 보자.

let add = (function() {
 let count = 0;
  
 return function() {
   return ++count;
 };
  
 console.log(count);
})();

add(); // 1
add(); // 2

add 변수는 외부 함수(IIFE)를 실행 한 결과를 저장한다. 처음 한 번만 실행되며 count를 0으로 설정하고 그 안에 함수 표현식을 반환한다.

IIFE가 생성 될 때 내부 기능이 실행되지 않는다는 점에 유의해야 한다. ++count가 실행되고 그 결과가 반환되기 전에 호출돼야 한다.

따라서 IIFE가 add에 할당되면 add()가 호출 될 때마다 내부 함수가 실행된다. 이렇게하면 업데이트 된 count 변수가 증가하고 반환된다. 이 코드를 실행한 후 콘솔에 나타나는 값은 내부 함수에서 반환한 업데이트 된 count 값이다.

profile
Hi, I'm dean. Front-end developer who likes UI/UX Design.

0개의 댓글