JavaScript

호이스팅

bas96 2021. 6. 19. 14:02

자바스크립트를 사용할 때 var를 쓰면 안되고 let과 const를 써야한다는 말을 많이 들었습니다.

왜냐하면 var는 호이스팅이 가능하기 때문에 혹시 실수로 같은 식별자로 선언을 2번했을 경우 찾기 어려운 오류를 만들 수 있기 때문이죠.

 

그런데 이번에는 var를 넘어서 Hoisting이 왜 일어나는지에 대해 더 자세히 알아보고 더 중요한 함수의 호이스팅에 대해서도 다뤄보겠습니다!


environmentRecord와 hoisting

자바스크립트가 실행 될 때 environmentRecord라는 것이 있는데 environmentRecord에서 호이스팅이라는 개념으로 식별자 정보들을 저장합니다. environmentRecord는 실행 컨텍스트를 다루며 더 자세하게 알아보겠습니다.

 

즉, '자바스크립트 엔진은 코드가 실행되기 전에 해당 환경에 속한 식별자들을 최 상단으로 끌어올린 다음에 실제 코드를 진행'합니다.

그런데 호이스팅은 변수 정보를 수집하는 과정을 이해하기 쉬운 방법으로 만든 가상의 개념입니다. 실제로 자바스크립트 엔진이 끌어올려 코드를 처리하지는 않지만 편의상 끌어올린 것으로 간주하는 것입니다.

바로 이것이 호이스팅의 개념입니다.

 

여기서 '식별자'란 

컨테스트를 구성하는 함수에 지정된 매개변수 식별자 (아래 예시에서는 x),

선언한 함수가 있을 경우 그 함수 자체 ,

var로 선언된 변수의 식별자 등

이 있습니다. (여기에서 var의 hoisting 개념이 나온 것입니다.)

 

매개 변수와 var로 선언된 변수의 Hoisting

environmentRecord 에는 위와 같은 식별자들이 담김니다.

먼저 매개변수와 var로 선언된 변수가 호이스팅 된 예시를 볼까요?

만약 호이스팅을 하지 않는다고 가정하면 첫 번째에는 1이 들어간 1

두 번째 콘솔로그에는 x가 선언만 되고 할당된 값이 없기 때문에 undefined

세 번째 콘솔로그에는 바로 앞에 선언한 2가 출력되었을 것 입니다.

 

하지만 호이스팅이라는 개념때문에 112가 출력되었습니다.

 

아래는 실제로는 일어나지 않지만 이해를 위해 호이스팅을 구현해본 모습입니다.

매개변수를 선언/할당과 같다고 가장해서 변환

호이스팅 과정을 구현한 위의 코드를 보시면 var로 선언한 변수가 그대로 위로 올라갔습니다.

할당된 값은 호이스팅되지않고 그대로 남아있죠? 그래서 var x 는 맨 위로 올라가고 밑에 있는 x= 1로 할당되었기 때문에 두 번째 콘솔로그에 undefined이 아닌 1이 나온 것입니다.

함수의 Hoisting

저는 함수를 처음 배울 때, '함수 선언문'과 '함수 표현식'이 있다, 그리고 사용하는 방법으로만 알고 있었습니다.

그런데 왜 그 두가지를 나누어서 사용하는지 궁금했지만 정확히 할지는 못했습니다. 그런데 함수의 호이스팅을 배우면 원리를 알고 사용할 수 있게 되었습니다.ㅎㅎ (유레카~~)

 

함수 선언문 & 함수 표현식

선언한 함수가 있을 경우 그 '함수 자체'가 호이스팅 된다고 했죠? 

결론부터 말씀드리면 "함수 선언문"은 함수 전체가 모두 호이스팅되고, (var로 선언된) 함수 표현식은 선언된 변수만 호이스팅되고, 함수는 밑에 남아있게 될 것입니다.

 

여기서 함수 선언문을 사용하면서 주의해야합니다. 아래 예시를 봅시다.

 

만약 실무에 엄청나게 긴 자바스크립트 코드를 만들었는 A라는 사람이 20번째 줄에 sum 이라는 함수를 선언하였고, 나중에 B라는 사람이 493번째 줄에 또 sum이라는 함수 선언을 하였으면 어떻게 될까요? 

만약 함수 선언은 호이스팅이 가능하다는 사실을 모르고 위에 sum함수가 선언된 것을 몰랐더라면, A,B가 만든 다른 sum함수는 모두 hoisting 되고, B가 만든 sum 함수 선언문이 모든 sum함수에 적용 될 것입니다. 이럴 경우 에러가 뜨지 않을 뿐더러 어디서 잘못된지 찾기도 어렵다는 문제점이 생깁니다.

 

하지만 만약 함수 표현식을 사용했었더라면 선언한 부분만 호이스팅 되고, A와 B의 각기 다른 sum함수는 각기 원하는 곳에 실행이 될 것입니다. (사실 이 예시는 전역변수에 함수를 선언했을 때의 예시이고, 이보다도 더 안전한 방법은 함수를 지역변수로 만드는 것입니다.)

 

결론적으로 

월활한 협업을 위해서는 전역 공간에 함수를 선언하거나, 같은 이름의 함수를 중복선언하지 않아야 한다.
혹시나 전역공간에 같은 함수가 여러 개 존재하더라도, 모든 함수가 '함수 표현식'으로 정의되어 있다면 오류를 잡을 수 있다.

+ 참고: 함수 선언문과 함수 표현식 정리

함수 선언문 함수 표현식
  • function 정의부분만 존재하고 별도의 할당 명령은 없는 것
  • 반드시 함수명이 정의되어있어야 함
  • 전체가 호이스팅 된다
  • 선언 전 호출을 하는 것이 가능하기 때문에 주의해야 한다.
  • 정의한 function을 별도의 변수에 할당하는 것
  • 함수명이 정의되어있지 않아도 괜찮다.
  • 일반적으로 함수 표현식은 익명 함수 표현식을 말한다.
  • 선언부만 호이스팅 된다
    (함수도 하나의 값으로 취급할 수 있다는 것의 의미가 바로 이런 것, 함수를 다른 변수에 값으로써 '할당'한 것)

 

 

2023년 2월 19일 (추가)

오랜만에 호이스팅 다시 보다가 함수 선언문 예시는 없어서 추가한다.

 

- 호이스팅 구현 상상