자바스크립트 호이스팅

박재현·2024년 3월 9일
0

JavaScript 공부

목록 보기
13/14

image soruce

호잇!스팅

호이스팅이란 코드가 실행되기 이전인 컴파일 단계에서 변수함수 선언이 포함된 스코프의 최상단으로 이동하는 자바스크립트의 동작을 말한다.

즉, 변수와 함수를 코드에서 선언하기 전에 사용할 수 있다!

(대충 심한 말)

그러나, 초기화가 아닌 선언만 호이스팅이 된다는점이 가장 중요한 포인트이다!


변수 호이스팅

var를 사용한 변수 선언은, 해당 스코프의 맨 위로 끌어 올려진다.

console.log(x); // undefined 
var x = 5; 
console.log(x); // 5

이는 호이스팅 중에 var x;는 맨 위로 이동하지만, 할당 부분 x = 5;는 그대로 유지된다.

따라서 스코프 최상단에서 x변수가 선언되어 있지만 아직 값이 할당되지 않은 상태인 undefined 라는걸 확인할 수 있다.

console.log(y); // ReferenceError: y is not defined 

let y = 10;        

하지만 letconst를 사용하면 호이스팅 동작이 달라지는데.
호이스팅은 되지만 초기화가 되지 않아 변수 선언 이전에 엑세스를 하려고 하면 참조에러가 발생하게 된다.


함수 호이스팅

먼저 함수는 크게 2가지 방법으로 선언해 사용할 수 있는데, 하나는 일반적인 함수 선언 방법이고 나머지는 함수 표현식 방법이 있다.

여기서 함수 선언문은 function func() {}을 말하고, 함수 선언식은 var func = function() {}을 말한다.

sayHello(); // "Hello, World!"

 function sayHello() {
 console.log("Hello, World!"); 
}   

위 코드를 통해서 알 수 있듯이, 함수 선언문을 사용해서 함수를 선언하면 호이스팅되어 함수가 실제로 선언되기 이전에 함수를 호출할 수 있다.

// This would result in a TypeError
 sayHi(); // TypeError: sayHi is not a function

 var sayHi = function() {
 console.log("Hi!"); 
};   

하지만 위 코드처럼 함수 선언식을 사용해서 함수를 사용하면 함수 호이스팅이 아니라 변수 호이스팅이 발생한다.

즉, sayHi는 변수 호이스팅이 발생해서 함수가 아닌 undefined가 된다.

따라서 is not a function이라는 에러가 발생하게 된다.

또한 화살표 함수 또한 함수 표현식을 작성하는 다른 방법이기 때문에, 변수 호이스팅이 발생해 is not function 에러가 동일하게 발생한다!


자바스크립트는 ES6의 let, const를 포함해서 모든 선언 var, let, const, function, function*, class를 호이스팅 한다.

여기서 호이스팅이란 var 선언문, function 선언문 등 모든 선언문이 해당 스코프의 최상단으로 옮겨진것 처럼 동작하는 특성을 말한다.

따라서 자바스크립트는 모든 선언문이 실제로 선언되기 이전에 참조가 가능하다.

함수 선언문으로 정의된 함수는 자바스크립트 엔진이 스크립트가 로딩되는 시점에 바로 초기화하고 이를 Variable Object(VO)에 저장한다.

즉, 함수 선언, 초기화, 할당이 한번에 이루어지기 때문에 함수 선언의 위치와 상관없이 소스 내 어느 곳에서든지 호출이 가능하다.

이와 다르게 함수 표현식은 스크립트 로딩 시점에 변수 객체(VO)에 함수를 할당하는게 아닌, runtime에 해석되고 실행되므로 함수를 생성한 코드 아래에서만 호출이 가능하다.

추가적으로 자바스크립트의 권위자 더글라스 크락포드는 함수 표현식만을 사용할것을 권고한다고 한다.

함수 호이스팅이 함수 호출 전 반드시 함수를 선언해야 한다는 규칙을 무시하기 때문에 코드의 구조를 엉성하게 만들 수 있다고 지적한다.
(즉, 함수가 호출되는데 이게 어떤 함수인지 모르면 안된다는 소리)

또한 함수 선언문으로 함수를 정의하면 사용하기에는 쉽지만, 규모가 커지면 인터프리터가 너무 많은 코드를 변수객체(Variable Object, VO)에 저장하므로 어플리케이션의 응답속도가 떨어질 수 있어 주의할 필요가 있다고 한다.


정리

변수 호이스팅

  • var를 사용해 변수를 선언하면, 호이스팅되어 변수 선언 이전에 undefined라는 값으로 참조할 수 있다.

  • let을 사용해 변수를 선언하면, 호이스팅은 되지만 초기화가 이루어지지 않아 선언 이전에 참조할 수 없다.

함수 호이스팅

  • 함수는 크게 2가지 방법으로 정의해서 사용할 수 있다.
  1. 함수 선언문
function func() {
  ...
}
  1. 함수 표현식 + 화살표 함수
var func = function() {
  ...
}
  
  or
  
var func = () => {
  ...
}

1번 처럼 함수 선언문을 이용하면, 실제로 함수가 선언되기 이전에도 해당 함수를 호출해서 사용할 수 있다.

이는 자바스크립트 엔진이 스크립트가 로딩되는 시점에 함수를 바로 변수객체(Variable Object)에 저장하기 때문인다.

2번 처럼 함수 표현식을 사용하면, 함수 호이스팅이 아닌 변수 호이스팅이 이뤄지고, 그러면 undefined라는 값으로 초기화 되기 때문에 이는 함수가 아니기에 에러가 발생한다.

자바스크립트의 권위자는 함수 선언문의 경우 실제로 함수를 정의하기 이전부터 호출할 수 있는 문제와 더불어서

함수 선언문의 경우 변수객체에 추가되기 때문에 규모가 커지면 불필요한 성능저하를 야기할 수 있으므로 2번처럼 함수 표현식으로 사용할것을 권고한다고 한다.


참고

profile
기술만 좋은 S급이 아니라, 태도가 좋은 A급이 되자

0개의 댓글

관련 채용 정보