Language/JS

[Javascript] 일반 함수 vs 익명 함수

개발하는 사막여우 2021. 5. 28. 15:52
반응형

자바스크립트는 유연한 언어이다. 따라서 다른 일반적인 언어(Java, C)와 다르게, 함수를 선언하고 사용하는데 있어 굉장한 자유로움이 주어진다. 이는 능숙한 사람에게는 굉장한 이점으로 주어질 수 있지만, 미숙한 사람에게는 넘어야 할 허들이 되기도 한다. 자바스크립트에서 함수 선언 방식은 기본적으로 일반 함수익명 함수로 나눌 수 있다.

 

1. 일반 함수 

일반적으로 다른 언어에서 사용하는 함수와 동일하다. 사용방식 또한 동일하며, 코드를 조금이라도 읽을 수 있는 사람이라면 매우 쉽게 이해할 수 있는 함수이다. 일반 함수는 다른 말로 함수 선언식이라고도 할 수 있다.

function 함수명(){
  함수 로직
}

// 예시
function SayHello(){
  console.log("hello!");
}

SayHello(); // 출력: hello!

 

일반 함수는 자바스크립트가 처음 읽힐 당시에 해석되므로, 함수가 쓰여진 위치가 상관없다. 이를 호이스팅이라고 하는데, 호이스팅이란 쉽게 말해 자바스크립트가 처음 읽힐 당시에 모든 객체(변수, 함수)의 선언부를 맨 위로 끌어올리는 것이다. 일반 함수는 함수 전체(함수명, 함수바디)가 통째로 호이스팅 되어 맨 위로 올라가기 때문에 위치 상관없이 읽을 수 있는 것이다.

SayHello(); // "hello!" 가 정상적으로 출력됨.

function SayHello(){
  console.log("hello!");
}

SayHello(); // "hello!" 가 정상적으로 출력됨.

// 호이스팅 된 모습
//
// function SayHello(){      <- 함수 선언이 먼저 일어나고,
//   console.log("hello!");
// }
//
// SayHello(); <- 첫 번째 SayHello();
// SayHello(); <- 두 번재 SayHello();

 

2. 익명 함수 

우선 익명함수 자체는 다음과 같은 형태를 가지고 있다. 일반 함수와 비교하여보면, 함수의 이름이 존재하지 않는다.

function() {
  console.log("hello!");
}

 

익명 함수는 재사용 하지 않는, 한번만 사용할 함수를 위한 개념으로, 따로 함수의 이름을 갖지 않는다. 리터럴(Literal) 방식으로 변수에 담겨 사용하는 함수이다. ("함수의 이름 != 변수" 임을 확실히 이해해야한다.)

리터럴(Literal) 방식이란 글자 뜻 그대로 "문자 그대로 읽히는 방식"을 의미하며, 일반적으로 변수에 데이터를 넣을 때 사용하는 방식이 리터럴 방식이다.

// 리터럴 방식

let a = 10;
const b = 20;

 

리터럴 방식으로 사용되는 익명 함수는, 변수에 저장되게 된다.

//익명 함수

const sayHello = function() {
  console.log("hello!");
}

sayHello(); // 출력: hello!

 

다시 한번 말하지만, 함수가 이름을 갖는 것과 변수에 저장되는 것은 다르다. 이 차이점은 어디서 오냐면, 위에서 언급한 호이스팅의 개념에서 온다. 위의 일반함수의 경우, 함수 전체가 전부 맨 위로 올라가므로 함수를 호출하는 위치에 상관없이 사용될 수 있다고 했다. 반면, 리터럴 방식으로 사용되는 익명 함수의 경우, 호이스팅 시 함수를 담는 변수의 선언부만 위로 올라가고, 익명 함수 자체는 변수가 호출되었을 때 실행되기 때문에, 선언부가 호출 위치보다 위에 있어야 한다. 코드로 보면 다음과 같다.

//익명 함수

sayHello(); // Uncaught ReferenceError: Cannot access 'sayHello' before initialization

let sayHello = function() {
  console.log("hello!");
}

sayHello(); // 위에서 에러가 났으니 출력이 나오지 않음

// 이 자바스크립트를 읽을 때(호이스팅 된 모습)
// 
// const sayHello;
//
// sayHello(); <- sayHello의 초기화가 진행되지 않았다.
// 
// sayHello = function(){
//   console.log("hello!");
// }
//
// sayHello(); <- 초기화는 진행된 후 불렸으니, 원래대로라면 출력 가능

 

 

 

3. 결론

1) 일반 함수는 전역적이며, 전체가 다 호이스팅 되므로 호출의 위치와 구현의 위치간에 연관관계가 없다. 또한, 재사용될 기능에 주로 사용된다.

2) 익명 함수는 선언부만 호이스팅되며 호출의 위치와 구현의 위치간에 순서가 알맞아야 하고, 한번만 사용하는 기능에 사용된다. 

 

위 말만 보면 익명 함수가 오히려 번거로운 것처럼 보일 수 있지만, 이는 메모리 관리에 효과적인 방안이 될 수 있다.

일반 함수는 자바스크립트를 초기에 읽어올 때 모두 호이스팅된다고 하였다. 만약, 전체 자바스크립트 내에서 단 한번만 쓰이는 함수가 일반 함수로 구현되어 있다고 가정해보자. 이 함수는 자신이 사용될 단 한번을 기다리며 불필요하게 메모리를 차지하고 있어야 한다. 메모리 사용량이 성능에 중요한 영향을 미칠 수 있는 웹 애플리케이션에서, 이는 메모리 낭비라고 볼 수 있다.

따라서 단 한번만 사용되는(재사용이 필요없는) 함수의 경우, 불필요한 시간동안 메모리를 차지하지 않도록 익명함수로 구현한다면, 정확히 해당 함수가 필요한 위치에서만 해당 함수가 구현되고 사라지면서 메모리를 아낄 수 있게 된다.

 


<참고>

https://joshua1988.github.io/web-development/javascript/function-expressions-vs-declarations/

https://hamdi.tistory.com/9

https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html

https://powerku.tistory.com/136

반응형