Front-end/JavaScript

JS 동작원리 6편 - 호이스팅

파리외 개발자 2022. 11. 6. 20:00

선언

변수 선언과 두 가지 방식의 함수 호출을 하고 선언을 그 이후에 해봤다.

일단은 세 가지 케이스 모두 오류는 없었지만 

선언형 함수 말고 변수와 함수 표현식의 one, say2는 undefined를 출력한다.

지금까지 위에서 아래로 읽어내려 오는 인터프리터 방식으로 JS를 해석한다고 알았다면

어째서 선언보다 호출이 먼저가 되어도 오류가 없는지 등에 대해

JS의 선언 방식에 대해 알아보자

 

변수 선언

위 코드의 세 번의 num콘솔 출력은 해당 시점의 num의 상태를 보여 줄 것이다.

선언을 하기 전에 호출할 때에는 undefined를 출력하고

그 이후엔 선언한 대로 값을 출력한다.

여기서 집중할 것은 처음의 undefined출력이다.

호이스팅이라 하는 JS의 변수 선언은 문서 전체를 읽기 전에 미리 예습하듯 선언이 된다. 단, 할당과는 다른 개념

var, let, const의 개념에 대한 선행을 추천한다.

변수는 선언과 할당이 있고

var는 선언 시 undefined를 미리 할당해두고 나중에 값을 할당해도 가능하지만

let은 선언 시 아무 값이 할당되지 않는 dead존이 있고 선언만 되고 할당이 안됬을 때 호출을 하면 참조 에러를

const는 아예 선언과 할당이 같이 이루어지지 않으면 에러를 낸다.

따라서 var라는 변수의 자유로운 성격 덕에 선언 전에 호출이 가능한 것처럼 보이지만

이는 혼란과 문제점을 야기할 수 있다. scope개념을 알고 있다면 이해가 더 빠를 수 있다.

var의 변수 선언은 원하는 값을 출력하기에 상당히 꼬일 수도 있다.

최대한 변수 선언에 var를 사용하는 것은 지양하도록 하고 선언은 호출보다 먼저 하는 것이 지향되는 추세다.

 

선언형 함수

첫 코드에서 선언형 함수만 유일하게 원하는 값을 출력받은 것을 기억한다면

선언형 함수 a를 제일 위에서 호출했을 때 어떤 값 일지 유추할 수 있을 것이다.

변수와 마찬가지로 함수도 hoisting으로 실행 전에 선언되는데

여기서 선언형 함수는 함수가 통째로 모두 선언된다.

따라서 yes의 내용인 a함수가 선언되었다가 바로 아래에서 no의 a함수로 재차 선언되며

실행단계에서는 마지막에 선언되었던 no가 출력되게 되는 것이다.

선언형 함수는 hoisting단계에서 전체 내용이 통째로 선언된다.

 

표현형 함수

마지막으로 함수를 변수에 저장하는 함수 표현식의 경우에는

hoisting단계에서 어떤 방식으로 선언이 될까?

var변수의 성질을 가진다면 undefined가 초기에 선언될 것이고

함수의 성질을 따른다면 전체 내용이 모두 호이스팅 될 것이다.

하지만 답은 이미 처음의 코드에서 알 수 있듯이 eat을 선언 전에 호출한다면

undefined를 출력할 것이다. 

그러므로 eat을 선언 후에 호출해보자

그런데 여기서 첫 문장의 food가 undefined를 출력한다.

전역 변수로 food에 rice를 선언했지만 이런 결과가 나오는 것은 scope의 개념과 관련이 있다.

함수는 통째로 호이스팅 되는 것과도 관련있는데 function은 global과 분리된 하위 집합으로써의

자신만의 영역을 가지고 있다. 따라서 만약 내부에 var food가 없었다면

global변수의 값을 가져다 썼겠지만 내부에 noodle이 선언됨으로써 호이스팅 시

함수 내부의 영역에서 또다시 변수가 호이스팅 되면서 global변수는 사용하지 않고

지역변수 food를 사용하며 선언보다 먼저 된 호출에 대해선 앞서 봤듯이 undefined를 출력하게 되는 것이다.

변수의 내용이 함수더라도 문장의 첫 단어가 var인지 function인지에 따라 호이스팅의 방향이 정해진다.