minzzl

[Javascript] 함수 선언문 vs 함수 표현식 본문

프로젝트/자바스크립트

[Javascript] 함수 선언문 vs 함수 표현식

minzzl 2022. 10. 8. 08:09
728x90
반응형

이 글에서는 함수 선언식과 함수 표현식에 대해 알아보도록 하겠습니다.

 

우선 Javascript에서의 함수의 개념과 특징에 대해 이야기해봅시다.

 

함수

- 프로그램을 구성하는 기본적인 building block

 

 

  • subprogram이라고도 하며 여러번 사용할 수 있다.
  • 한 가지의 task나 값을 계산
  • 여러 개의 인자를 받아서, 그 결과를 출력합니다.
  • 파라미터의 개수와 인자의 개수가 일치하지 않아도 오류가 발생하지 않는다.

- 만약, 파라미터 1개가 정의된 함수를 부를 때, 인자의 개수를 0개만 넣어 실행하면 이미 정의된 파라미터(매개변수)는 undefined이라는 값을 갖게 되는데 이는 변수는 초기화됐지만, 값이 할당되지 않았기 때문입니다.

  • Javascript에서는 함수도 객체다.

- 따라서 다른 객체와 마찬가지로 넘기거나 할당할 수 있습니다.

- 함수를 객체 프로퍼티에 할당할 수도 있습니다.

 const o = {}
  o.f = testFunc
  o.f() // test!!


- 함수를 객체 배열 요소로 할당할 수도 있습니다.

const arr = [1, 2, 3]
  arr[1] = testFunc
  arr[1]() // test!!

 

Callback function

  • 함수의 매개변수로 함수를 전달
  • 함수 안에서 조건에 따라 매개변수로 전달된 함수 실행
 function quiz(ans, printYes, printNo) {
     if (ans == 'ok') {
         printYes();
     } else {
         printNo();
     }
 }

 // anonymous function
 const printYes = function() {
     console.log('yes');
 }

 // named function
 // debugging할 때 쓰거나 recursion에 사용
 const printNo = function() {
     console.log('no');
 }

 quiz('ok', printYes, printNo);
 // yes
 quiz('idk', printYes, printNo);
 // no

 

Arrow function

  • 함수를 바로 실행함
 // function express
 const sample1 = function() {
     console.log("Hello");
 }

 // Arrow function (only return)
 const sample2 = () => console.log("World");

 // Arrow function (use parameter with task)
 const sample3 = (a, b) => {
     a++;
     return (a + b);
 }

 

IFE: Immediately Invoked Function Expression

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

 

함수 호출 vs  함수 참조

 

함수 호출

  function printName(firstname) {
    var myname = "HEEE";
    return myname + " " +  firstname;
  }
let name = printName() // 함수의 호출
console.log(name)

함수 식별자 뒤에 괄호를 쓰면 함수 본문을 실행하며 함수를 호출한 표현식은 반환값이 됩니다.

 

함수 참조

  function printName(firstname) {
    var myname = "HEEE";
    return myname + " " +  firstname;
  }
const printNamefunc = printName // 함수의 참조
let name = printNamefunc()
console.log(name)

위의 코드와 같이 함수를 변수에 할당하면 printNamefunc()과 같이 다른 이름으로 함수를 호출할 수 있습니다.

 

.

.

.

 

함수에 대한 기본적인 이야기는 한 것 같으니, 본격적으로 함수 선언식과 함수 표현식에 대해 알아봅시다.

 

함수 선언식

- 함수명이 정의되어 있고, 별도의 할당 명령이 없는 것

 

 변수 선언이 let이나 const로 시작해야하는 것처럼 함수 선언을 function으로 시작합니다. 또한 선언된 함수는 나중 사용을 위해 저장되며, 함수를 실행하려면 함수 이름을 호출(call)하면 됩니다.

function sum(a,b) {
    return a + b;
}

sum(2,4)

 

함수 표현식

- 정의한 함수를 별도의 변수에 할당하는 것

const sum = function(a,b) {
    return a + b;
}

 

함수 선언식과 함수 표현식은 호이스팅에서 차이가 발생합니다. 사실 우선 둘의 차이는 호이스팅을 빼놓고 설명할 수 없습니다.

 

 

함수 선언식은 함수 전체를 호이스팅합니다. 정의된 범위의 맨 위로 호이스팅이 되어 함수 선언 전에 함수를 사용할 수 있습니다.

자바스크립트는 선언만 호이스팅하기 때문에 함수 선언식은 var 문과 유사하게 호이스팅이됩니다. 

alert(foo()); 
// Alerts 5. 
// 선언 전에 호출되도 정상 동작

function foo() { return 5; }

 

반면에 함수 표현식은 호이스팅이 되지않습니다.  함수 표현식은 별도의 변수에 할당하게 되는데, 변수는 선언부와 할당부를 나누어 호이스팅하게됩니다. 자바스크립트는 선언만 호이스팅할 뿐, 초기값 할당에 대한 부분은 호이스팅하지 않습니다. 따라서 선언만 호이스팅 되고 그 값은 undefined로 지정됩니다.  

alert(foo()); // Uncaught TypeError: count is not a function 에러 발생! foo 함수는 아직 로드안됨
var foo = function() { return 5; }

즉 var 는 호이스팅의 영향을 받으므로 위로 끌어올려지며 변수에 아무 값도 담지 않았으므로 undefined 상태입니다. foo()가 호출되면 위에 선언한 count가 호출되므로 변수를 호출하는 격이되므로 not function 이라는 에러 메시지가 나타납니다.  

 

count(); //Uncaught ReferenceError: c is not defined

let count = function() {
    console.log('count는 1이다.');
}

세번째 예시는 첫번째 예시에서 var 를 let으로 바꾼 것인데요, 세번째도 역시 에러를 발생하지만, 첫번째와 다른 Referecne Error가 발생합니다.
let 은 호이스팅의 영향을 받지만, 선언만 이루어지고 초기화는 되지 않았기 때문에 TDZ에 들어간 상태일 것이고, 즉 아직 값이 초기화 되지 않았기 때문에 Reference err 를 초래합니다.

일반적으로 함수 선언식과 함수 표현식은 함께 사용할 수는 있지만, 함수 표현식은 함수 이름이 필요없기에 가독성이 더 높은 장점이 있습니다.

함수 선언식과 비교하여, 함수 표현식의 이점은 아래와 같습니다. 해당 내용은 향후 Javascript의 이해도가 조금은 더 올라갔을 때 소개해보도록 하겠습니다.

1. 클로저
2. 인자 전달
3. IIFE(즉시 주입 함수 표현식)

 

 

 

 

 

 

 

* 아래의 글을 바탕으로 작성하였습니다.

https://velog.io/@bisu8018/%ED%95%A8%EC%88%98-%ED%91%9C%ED%98%84%EC%8B%9D-VS-%ED%95%A8%EC%88%98-%EC%84%A0%EC%96%B8%EC%8B%9D

https://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html

728x90
반응형