[JS] 실행 컨텍스트 - 함수 선언문과 함수 표현식

이승혜·2021년 9월 4일
0

JS/JQUERY

목록 보기
6/10
post-thumbnail

이 글은 📕코어 자바스크립트 책을 바탕으로 정리한 글입니다.

이 글은 👇이전 포스터👇와 이어지는 내용입니다.
[JS] 실행 컨텍스트 - environmentRecord와 호이스팅

💡 함수 선언문과 함수 표현식

함수 선언문과 함수 표현식이 호이스팅과 어떤 관련이 있는 지 알아보기 전에, 함수 선언문과 함수 표현식에 대해 짚고 넘어가보자

함수 선언문(function declaration)과 함수 표현식(function expression) 모두 함수를 새롭게 정의할 때 쓰이는 방식이다.
함수 선언문은 function 정의부만 존재하고 별도의 할당 명령이 없는 것을 의미하고, 함수표현식은 정의한 function을 별도의 변수에 할당하는 것을 말한다.

function a(){...} // 함수 선언문. 함수명 a가 곧 변수명
a(); // 실행 OK
             
var b = function(){...} // (익명)함수 표현식. 변수명 b가 곧 함수명           
b(); // 실행 OK
                   
var c = function d(){...} // 기명 함수 표현식. 변수명은 c, 함수명은 d
c(); // 실행 OK
d(); // 에러!

📌 함수명을 정의한 함수표현식을 '기명 함수 표현식'이라고 한다.
기명 함수 표현식은 외부에서 함수명으로 함수를 호출할 수 없다.
위 예제에서 c 함수 내부에서는 c()로 호출하든 d()로 호출하든 잘 실행되기에 함수 내부에서 재귀함수를 호출하는 용도로 쓸 수 있다.
하지만 c()로 호출해도 되는 상황에서 굳이 d()로 호출해야할 필요는 없음 (결론은 잘 안쓰인다)

함수 선언문과 함수 표현식의 실질적인 차이

원본 코드 예제

console.log(sum(1, 2));
console.log(multiply(3, 4));

function sum(a, b) { // 함수 선언문 sum
  return a + b;
}

var multiply = function (a, b) { // 함수 표현식 multiply
  return a * b;
};

실행 컨텍스트의 lexicalEnvironment는 두 가지 정보를 수집하는데, 여기서는 environmentRecord의 정보 수집 과정에서 발생하는 호이스팅을 살펴보자

호이스팅을 마친 상태

// 함수 선언문은 전체를 호이스팅 한다.
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;
};

함수 선언문은 전체를 호이스팅한 반면 함수 표현식은 변수 선언부만 호이스팅 하는 것을 볼 수 있다.
함수도 하나의 값으로 취급할 수 있다는 것이 바로 이런 것이다.
함수를 다른 변수에 값으로써 '할당'한 것이 곧 함수 표현식이다.

위 코드를 실행해보면

다음과 같은 결과가 나온다
sum(1,2)는 정상적으로 실행되어 3이 출력되지만
multiply에는 값이 할당돼 있지 않기 때문에 'multiply is not a function'이라는 에러 메시지가 출력되며 런타임이 종료된다.

함수 선언문의 위험성

위 예제의 sum 함수는 선언 전에 호출해도 아무 문제 없이 실행된다.
어떻게 작성해도 오류를 내지 않는다는 면에서 초급자들이 JS를 좀 더 쉽게 접근할 수 있게 해주는 측면도 있지만, 반대로 큰 혼란을 일으키는 원인이 되기도 한다.

예를 들어 개발자 A가 sum이라는 함수를 파일 내 100번째 라인에 작성을 했다고 치자.
새로 입사한 개발자 B가 같은 파일의 5000번째 라인에 sum함수를 새로 선언한다면?

전역 컨텍스트가 활성화될 때 전역공간에 선언된 함수들이 모두 가장 위로 끌어올려진다.
동일한 변수명에 서로 다른 값을 할당할 경우 나중에 할당한 값이 먼저 할당한 값을 덮어씌운다(override).

만약 개발자 A와 B 모두 sum함수를 함수 표현식으로 정의했다면 어땠을까?
5000번째 줄 이전까지는 A의 의도대로, 5000번째 줄 이후부터는 B의 의도대로 잘 동작했을 것이다.

🙄 위와 같은 상황을 피하기 위해 함수 표현식으로 쓰는 습관을 들이자!

profile
더 높이

0개의 댓글