JavaScript | 함수 선언문 vs. 함수 리터럴

함수 선언문 vs 함수 리터럴

함수 선언문과 함수 리터럴은 형태가 동일하다. 그러면 자바스크립트는 어떻게 해석하는가?

문맥에 따라 함수 선언문이여야 하는지, 함수 리터럴이여야 하는지를 판단한다.

아래 예제를 보자.

// 함수 리터럴
var add = function add(x, y) {
  return x + y;
}

// 함수 호출
console.log(add(2, 5)); // 7

위에서 function add를 함수 선언문이라고 가정하면, 할당 연산자에 의해서 변수에 값이 할당될 수 있어야 한다.

즉 함수 선언문은 값으로 평가될 수 있어야 한다. 하지만 함수 선언문은 표현식이 아닌 문, 즉 값으로 평가될 수 없으므로

해당 자리에는 함수 선언문이 올 수 없다.

따라서 값으로 평가될 수 있는 함수 리터럴이 와야하는 자리이므로, 자바스크립트는 function add를 함수 표현식으로 해석한다.

함수 선언문과 함수 리터럴의 내부 동작 차이

// 함수 선언문
function foo() {
  console.log("foo");
}
foo();

// 함수 리터럴
(function bar() {
  console.log("bar");
});
bar(); // ReferenceError: bar is not defined

함수 선언문 foo

단독으로 사용되었으므로 함수 선언문으로 해석된다.

함수 이름으로는 함수 외부에서 함수를 참조할 수 없다.

함수 선언문의 경우엔 함수 객체를 가리키는 식별자를 함수가 포함된 스코프에 암묵적으로 생성한다.

즉 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다.

따라서 함수 선언문으로 생성된 foo는 호출할 수 있다.

함수 리터럴 bar

그룹 연산자 ()의 피연산자는 값으로 평가될 수 있는 표현식이여야한다. 따라서 함수 리터럴 표현식으로 해석된다.

함수 이름으로는 함수 외부에서 함수를 참조할 수 없다.

함수 리터럴로 생성된 함수는 함수를 가리키는 식별자가 없으므로 bar함수는 호출할 수 없다.

함수는 함수 이름으로 호출하는 것이 아니라, 함수 객체를 가리키는 식별자로 호출한다.

따라서 아래와 같이 함수 리터럴에 식별자를 붙여주면 함수 외부에서 함수 호출이 가능해진다.

// f: 식별자, add: 함수 이름
var f = function add(x, y) {
  return x + y;
};

// 식별자로 함수를 호출한다
console.log(f(2, 5)); // 7

console.log(add(2, 5)); // ReferenceError: add is not defined

좋은 웹페이지 즐겨찾기