본문 바로가기

Frontend Study - 2/Javascript

Javascript : 함수 선언식과 함수 표현식 비교

자바스크립트에서 함수를 생성하는 방법 중 함수 선언식, 함수 표현식을 비교해 보려고 한다. 

 

 

1. 함수 선언식

function counter(x) {
	return x+1
}

 

2. 함수 표현식

const counter = function(x) {
	return ( x+1 )
}

 

 

- 함수 선언식과 함수 표현식의 차이점.

 

생김새가 비슷하지만, 표현식의 경우 함수를 변수안에 저장을 해두었다는 점에서 다르다. 

표현식은 일반적으로 선언한 변수명을 함수명으로 대체한다. 

 

주요한 차이점은 호이스팅이다.

 


counter(3)    //4
newCounter(3)    // error


function counter(x) {
	return x+1
}
    
const newCounter = function(x) {
	return ( x+1 )
}

 

코드 아래에서 선언식, 표현식으로 각각 함수를 만들었고, 위에서 두 함수를 호출했다. 

 

첫번째 줄에서 호출한 counter 함수의 경우 4 라는 값이 리턴되었지만, 

아래의 표현식으로 만든 newCounter 함수에서는 값이 리턴되지 못했다. 

 

선언식 함수는 전체가 호이스팅 되는 반면, 

함수 표현식의 경우 선언하는 부분과 할당하는 부분 중 선언하는 부분만 호이스팅 되기 때문이다. 

위 코드의 실행 순서를 나타내면 아래와 같다. 

 

function counter(x) {   //// 함수 선언식 호이스팅
	return x+1
}

const newCounter   /// 함수 표현식 중 선언 부분만 호이스팅 

counter(3)    //4
newCounter(3)    // Uncaught TypeError


= function(x) {   // 함수 표현식 중 할당 부분은 호이스팅 되지 않음.
	return ( x+1 )
}

 

이 밖에도 선언식 함수와 구분되는 표현식 함수의 특징들이 있다. 

 

1) 클로저로 사용될 수 있다.

 

※ 클로저(closure)란?

함수와 함수가 선언된 어휘적 환경의 조합이다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.

내부함수가 외부함수의 맥락에 접근할 수 있는 것. 선언된 환경이 아닌 곳에서 호출되었을 때 선언된 환경에 접근할 수 있는 것.

 

const animal = "dog"; // 외부에서 animal 선언

function findAnimal() {
  const animal = "cat";  // 내부에서 animal 선언
  
  function clouser() {
    console.log(animal);
  }
  return clouser;
}

findAnimal() // nothing. 그냥 clouser함수를 'return' 할 뿐 실행하지는 않음. 

const reference = findAnimal(); // 함수 표현식을 사용하여 내부 함수(clouser)를 리턴. 변수에 담는다.
reference(); // 출력: cat; 내부함수 실행. 특히 reference의 스코프는 전역임에도 불구하고 func안에 있는 변수를 출력

 

 

2) 콜백으로 바로 사용될 수 있다.

-> 다른 함수의 인자로 바로 넘길 수 있다. 즉, 선언하는 과정 없이 그대로 쓸 수 있다.

 

const findFood = function () {
  console.log("chicken");
};

function sayFood(func) {
  func();
}

sayFood(findFood);


--->

sayFood(function() {
	console.log("chicken")
   })

 

 

3) 즉시 실행함수(IIFE)로 사용될 수 있다.

 

()() -> 이러한 형식이다.  전체 함수를 () 괄호로 감싸주어서 내부의 함수가 표현식으로 해석될 수 있게 한다.

전역 스코프에 불필요한 변수를 추가해서 오염시키는 것을 방지할 수 있고 IIFE 내부로 다른 변수들이 접근하는 것을 막을 수 있다고 한다.

;(test = function() {
  console.log('test')
})() // "test"

 

 

무기명으로도 사용이 가능하다.

;(function() {
  console.log('hello')
})() // "hello"