| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- 분할정복
- 해시함수
- 힙트리
- 상수시간
- 자료구조
- 리렌더링
- 해시테이블
- 백준
- hash table
- 얕은비교
- 균형이진트리
- quadratic probing
- literal
- 삽입
- 리액트
- 힙정의
- null병합 연산자
- 자바스크립트
- 함수표현
- 힙성질
- 원시타입
- 호이스팅
- 알고리즘
- heapify
- 함수선언
- 옵셔널체이닝
- 참조값
- 원시값
- 리터럴
- 참조타입
- Today
- Total
천천히 하지만 더 멀리
자바스크립트 [ 함수 선언문 vs 함수 표현식 ] 본문
함수 리터럴
함수도 객체타입의 값이므로 함수도 함수 리터럴로 생성할수 있다.

⭐️ 함수 리터럴은 평가가 되어 값을 생성한다. 함수를 통해 생성된 값은 객체이다!
함수는 일반객체와 달리 호출을 할수 있고, 고유한 프로퍼리를 가지고 있다.
함수 정의 방법
1. 함수 선언문
function add(x,y) {
return x + y;
}
함수 선언문은 반드시 함수의 이름을 써주어야 한다.
함수 선언문은 표현식이 아니라 '문'이다. 문은 표현식과 다르게 변수에 할당이 안된다. 하지만 함수 선언문은 함수 리터럴과 이름을 넣어줘야 한다는 조건 말고는 똑같다. 따라서 자바스크립트 엔진은 코드 문맥에 따라 함수 선언문을 함수 리터럴 표현식으로 해석할수도 있다.
var add = function add(x, y) {
return x + y;
}
함수 선언문이나 함수 리터럴 표현식이나 함수를 생성하는 것은 똑같다. 하지만 함수 호출에서 차이가 있다. 우리는 함수의 이름은 함수 몸체 내부에서만 참조할수 있다고 알고 있다. 이 내용을 명심하고 다음 예제를 한번 살펴보자.
// 함수 선언문
function foo() { console.log('foo'); }
foo(); // 'foo'
// 함수 리터럴 표현식 ( 함수 선언문은 표현식으로 사용할수 없으므로 함수 리터럴이다 )
(function bar() { console.log('bar'); }
bar(); // ReferenceError: bar is not defined
위 예제를 보면 함수 선언문으로 만들어진 foo 함수는 정상적으로 호출이 되었다. 하지만 함수 리터럴 표현식으로 생성된 함수는 호출할때 에러를 발생시켰다. 무슨 차이일까? 우리는 함수의 이름은 함수 몸체에서만 참조할수있다고 하였다. 즉 함수 선언문과 함수 리터럴 표현식 모두 식별자가 없는 상태인것이다. 어?? 그런데 함수 선언문으로 만들어진 foo 함수는 어떻게 호출이 될수 있을까? 메모리 주소가 어떻게 할당 되었는지 알아보자.

위 그림에서 보는 바와 같이 함수 리터럴 표현식에서는 함수를 가리키는 식별자가 없는 반면에 함수 선언문으로 생성된 foo 함수는 함수 식별자가 foo 라고 있다. 이것은 자바스크립트 엔진이 암묵적으로 함수와 같은 이름으로 식별자를 생성하고 foo 식별자에 함수 객체를 할당한것이다. 따라서 함수 리터럴 표현식으로 만들어진 함수는 식별자가 없다는 에러가 난것이고 함수 선언문으로 만들어진 foo 함수는 정상적으로 호출이 된것이다.
2. 함수 표현식
함수는 일급객체(값의 성질을 갖는 객체)이므로 변수에 할당할수 있다. 이러한 함수 정의 방식을 함수표현식이라고 한다.
var add = function(x, y) {
return x + y;
}
console.log(add(3, 4)); // 7
⭐️ 함수 선언문과 함수 표현식의 차이 ⭐️
함수 선언문과 함수 표현식이 유사하게 작동 하는 것처럼 보이지만 미묘한 차이가 존재한다. 먼저 예시를 살펴보자
// 함수 참조
console.dir(func_dec_add); // f func_exp_add(x, y)
console.dir(func_exp_add); // undefined
// 함수 호출
console.log(func_dec_add(2, 4)); // 6
console.log(func_exp_add(2, 4)); // TypeError: func_exp_add is not function
// 함수 선언문
function func_dec_add(x, y) {
return x + y;
}
// 함수 표현식
var func_exp_add = function(x, y) {
return x + y;
}
함수 선언문으로 정의한 함수는 정상적으로 호출이 되고, 함수 표현식으로 정의한 함수는 호출시 타입에러를 내뱉었다. 왜 이렇게 다르게 동작할까? 먼저 자바스크립트 엔진은 런타임 전에 코드를 한줄한줄 읽으며 모든 선언문을 실행한다. 이 과정에서 함수 선언문으로 정의된 함수는 암묵적으로 함수의 이름으로 식별자가 생성되고 함수객체가 생성되어 식별자에 할당까지 완료한다. 즉 식별자가 런타임 전에 함수객체를 참조를 하는 것이다. 그래서 console.dir(func_dec_add) 의 결과가 함수 객체가 찍힌것이다. 이렇게 함수 선언문이 코드의 선두로 끌어 올려진것처럼 동착하는 것을 함수 호이스팅이라고 한다.
함수 표현식을 이제 살펴보자. 함수표현식이 함수를 정의하는 것은 var 키워드를 사용한 변수에 함수 리터럴을 할당하는 방식이다. var 키워드로 변수를 할당하면 런타임 전에 변수가 선언되고 undefined 로 초기화 된다. 실제 런타임 환경에서는 변수에 함수 리터럴이 할당되기 전에 초기화에 의해 할당된 undefined 를 호출하게 되어서 type error 가 생기는 것이다. 이 경우 함수선언문과 같이 함수 호이스팅이 아닌 변수 호이스팅이 발생된것이다.
함수를 선언하기 전에 함수를 호출하는 일을 방지하기 위해서 함수 선언문보다 함수 표현식을 쓰기를 권장하는 추세이다.
Reference
책 모던자바스크립트 Deep Dive
'JavaScript' 카테고리의 다른 글
| [ 자바스크립트 ] 단축 평가 (0) | 2022.01.09 |
|---|---|
| Javascript 표현식과 문 (0) | 2021.12.26 |
| Javascript [ 변수 ] (0) | 2021.12.26 |
| 원시값(Primitive value) vs 참조값(Reference value) (0) | 2021.12.22 |