minzzl
[Javascript] 함수 선언문 vs 함수 표현식 본문
이 글에서는 함수 선언식과 함수 표현식에 대해 알아보도록 하겠습니다.
우선 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://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html
'프로젝트 > 자바스크립트' 카테고리의 다른 글
[Javascript] operator와 loop,if (0) | 2022.10.08 |
---|---|
[Javascript] 호이스팅 (0) | 2022.10.08 |
[Javascript] 데이터타입 let var const (1) | 2022.10.07 |
[Javascript] async 와 defer의 차이점 (1) | 2022.10.06 |