함수 선언문과 함수 표현식
함수 선언문(function declaration)은 function의 정의부만 존재하고 별도의 할당 명령이 없는 것을 의미합니다.
function a() { // 함수 선언문
/* ... */
}
a(); // 정상 실행
함수명 a
가 곧 변수명입니다. 함수 선언문의 경우 반드시 함수명이 정의되어 있어야 합니다.
반대로 함수 표현식(function expression)은 정의한 function을 별도의 변수에 할당하는 것을 말합니다.
var b = function () { // (익명) 함수 표현식. 변수명 b가 곧 함수명
/* ... */
}
b(); // 정상 실행
var c = function d () { // 기명 함수 표현식. 변수명은 c, 함수명은 d
/* ... */
}
c(); // 정상 실행
d(); // 에러 발생
기명 함수 표현식은 외부에서 함수명으로 함수를 호출할 수 없기 때문에 주의해야 합니다. 함수명은 오직 함수 내부에서만 접근할 수 있습니다.
함수 선언문의 위험성
함수 선언문은 함수 전체가 끌어올려져 선언과 할당이 동시에 이뤄집니다. 따라서 같은 이름의 함수가 선언되어 있다면 가장 나중에 있는 함수로 덧씌워져버려 문제가 발생할 수 있습니다.
함수 선언문과 표현식의 호이스팅을 이해하기 다음 예제를 실행시켜 보겠습니다.
console.log(sum(1, 2));
console.log(multiply(3, 4));
function sum(a, b) {
return a + b;
}
var multiply = function (a, b) {
return a * b;
};
/* 출력 결과
3
오류 발생 --> TypeError: multiply is not a function
*/
자바스크립트는 함수 선언문 전체를 호이스팅하는 반면 함수 표현식은 변수 선언부만 호이스팅합니다. 호이스팅을 마친 최종 상태(실제로 이렇게 되지 않지만 이해를 쉽게 하기 위한 코드)는 다음과 같습니다.
// 함수 선언문 전체를 호이스팅
var sum = function sum(a, b) {
return a + b;
};
var multiply; // 변수는 선언부만 호이스팅
console.log(sum(1, 2));
console.log(multiply(3, 4));
// 변수의 할당부는 원래 자리에 남겨놓습니다.
multiply = function (a, b) {
return a + b;
};
자바스크립트는 함수를 하나의 값으로 취급할 수 있습니다. 자바스크립트가 코드 실행 전 함수 선언문을 만나면, 함수 이름과 같은 변수를 선언하고 만들어 함수 선언문 전체(즉, 함수)를 할당합니다. 하지만 함수 표현식을 만나면 변수명만 끌어올려 선언합니다.
이 원칙은 나중에 치명적인 문제를 일으킬 수 있습니다.
console.log(sum(3, 4));
function sum(x, y) {
return x + y;
}
var a = sum(1, 2);
console.log(a);
function sum(x, y) {
return x + "+" + y + " = " + (x + y);
}
var c = sum(1, 2);
console.log(c);
/* 출력 결과
3+4 = 7
1+2 = 3
1+2 = 3
*/
위 함수 선언문으로 작성된 코드는 아래와 같이 호이스팅 됩니다.
var sum = sum(x, y) {
return x + "+" + y + " = " + (x + y);
}
var a;
var c;
console.log(sum(3, 4));
a = sum(1, 2);
console.log(a);
c = sum(1, 2);
console.log(c);
이 코드의 작성자는 sum
함수를 재정의 하여 문자열로 출력하려고 했지만, 이미 처음부터 sum 함수는 가장 아래 선언문으로 덧씌워진 상태입니다.
즉, 의도한 대로 프로그램이 실행되지 않을 수 있습니다.
하지만 함수를 함수 표현식으로 작성한다면 어떻게 될까요?
console.log(sum(3, 4));
var sum = function sum(x, y) {
return x + y;
}
var a = sum(1, 2);
console.log(a);
var sum = function sum(x, y) {
return x + "+" + y + " = " + (x + y);
}
var c = sum(1, 2);
console.log(c);
/* 출력 결과
3+4 = 7
1+2 = 3
1+2 = 3
*/
위 코드는 아래와 같이 호이스팅 됩니다.
// 호이스팅된 이후 코드 (실제로 이렇게 실행되는 것은 아니지만, 해석을 위해)
var sum;
var a;
var c;
console.log(sum(3, 4)); // TypeError: sum is not a function
sum = function sum(x, y) {
return x + y;
};
a = sum(1, 2);
console.log(a);
sum = function sum(x, y) {
return x + "+" + y + " = " + (x + y);
};
c = sum(1, 2);
console.log(c);
결론
함수 표현식이 안전하다. 함수 표현식 쓰자.
출처 및 참고 문헌
- 책 <코어 자바스크립트>
'프로그래밍-학습기록 > Javascript' 카테고리의 다른 글
Javascript Koans가 뭐야? 설명과 테스트 후기 (0) | 2021.02.19 |
---|---|
[Javascript] 프로토타입으로 클래스 구현하기 (0) | 2021.02.17 |
[Javascript] 프로토타입 찬찬히 이해해보기 (0) | 2021.02.16 |
클로저는 글로 적기 글렀어. (0) | 2021.02.15 |
자바스크립트 콜백 함수 이해하기 (0) | 2021.02.13 |