함수란 입력을 받아 출력을 내보내는 일련의 과정이다.
자바스크립트 함수는 4가지 방법으로 정의할 수 있다.
자바스크립트의 함수는 객체 타입의 값이다.
따라서 함수를 변수에 값처럼 할당할 수 있으며
다음과 같은 방식으로 함수를 정의할 수 있다.
var getSum = function add(x, y) {
return x+y;
};
console.log(add(2, 3)); // ReferenceError
console.log(getSum(2, 3)); // 5 출력
위의 코드에서 getSum 변수에 함수 리터럴을 할당하였다.
이와 같이 함수를 정의하는 방식을 함수 표현식이라 한다.
보통 우리는 함수의 이름을 사용하여 해당 함수를 호출한다.
그런데 위의 코드에서는 add(2, 3)으로 함수를 호출하니 add 가 정의되지 않았다는 에러가 발생하였다.
왜 그럴까 ❓
우리는 먼저 함수 이름과 함수 객체를 참조하는 식별자를 구분해서 생각해야 한다.
위의 코드에서 함수 이름은 add 이고,
함수 객체를 참조하는 식별자는 getSum 이다.
자바스크립트에서 함수 이름은 함수 외부에서 참조할 수 없으며 함수 몸체 내부에서만 참조할 수 있다!
그렇기 때문에 add(2, 3) 로 함수를 호출하니 add 가 정의되지 않았다는 에러가 발생한 것이다!
이번에는 함수 선언문의 방식을 이용하여 함수를 정의한 예제 코드를 살펴보자.
function add(x, y) {
return x+y;
}
console.log(add(2, 3)); // 5 출력
위의 코드에서 add 이름을 갖는 함수를 정의하고,
add(2, 3) 으로 함수를 호출하였다.
함수 표현식과 다르게 함수 선언문은 함수 이름으로 함수를 호출했음에도 불구하고 에러가 발생하지 않았다.
왜 그럴까 ❓
함수 선언문으로 함수를 정의하면 자바스크립트 엔진은 함수 이름으로 식별자를 암묵 생성하고 생성된 함수 객체를 할당한다.
따라서 함수 이름과 함수 객체를 참조하는 식별자가 동일한 이름을 갖게 된다.
그렇기 때문에 함수 이름으로 함수를 호출해도 오류가 발생하지 않는다.
사실은 함수 이름이 아닌 함수 객체를 참조하는 식별자로 호출하는 것이기 때문이다 ❗️
아래는 Function 생성자 함수를 이용하여 함수를 정의하는 예시다.
var add = new Function('x', 'y', 'return x+y');
console.log(add(2, 3)); // 5 출력
자바스크립트가 기본 제공하는 빌트인 함수인 Function 생성자 함수에 매개변수 목록과 함수 몸체를 문자열로 전달하면서 new 연산자와 함께 호출하면 함수 객체를 생성해서 반환한다.
그러나 Function 생성자 함수로 함수를 생성하는 방식은 일반적이지 않으며 바람직하지도 않다.
아래는 화살표 함수를 이용하여 함수를 정의하는 예시다.
const add = (x, y) => x + y;
console.log(add(2, 3)); // 5 출력
ES6에서 도입된 화살표 함수는 function 키워드 대신 화살표를 사용해 좀 더 간략한 방법으로 함수를 선언할 수 있다.
화살표 함수는 항상 익명 함수로 정의한다 ❗️
그렇다면 함수 선언문도 변수처럼 호이스팅될까 ❓
호이스팅이란?
선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징이다.
변수, 함수 등의 선언문은 런타임 이전에 먼저 실행된다!
결론부터 말하자면 함수 선언문은 호이스팅되며,
함수 표현식은 변수 호이스팅이 발생하며 함수 호이스팅은 되지 않는다.
// 함수 표현식
var add = function (x, y) {
return x+y;
};
// 함수 선언문
function add(x, y) {
return x+y;
}
위 코드의 함수 표현식에서 함수 리터럴을 add 변수에 할당하고 있다.
이때, 변수 add 는 런타임 이전에 선언되며 함수 객체는 런타임에 생성되어 변수 add 에 할당된다.
위 코드의 함수 선언문에서는 런타임 이전에 함수 객체가 생성된다.
그리고 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당한다.
-끝-
잘못된 정보, 오탈자를 발견하면 편하게 댓글로 말씀해주시면 감사하겠습니다 🙂