자바스크립트 공부를 시작해봅시다.
“자바스크립트를 잘 이해하고 있다는 것” === “자바스크립트 함수를 잘 이해하고 있다는 것”
호이스팅(Hoisting)이란?
함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.
선언문은 항시 자바스크립트 엔진 구동시 가장 최우선으로 해석하고, 할당 구문은 런타임 과정에서 이루어지기 때문에 호이스팅되지 않는다.
호이스팅이 나오게 된 계기가 함수나 변수의 선언과 할당의 순서를 구분짓기 위함이라고 생각합니다.
- 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값을 모두 모아서 유효 범위의 최상단에 선언한다.
- 자바스크립트 Parser 가 함수 실행 전 해당 함수를 한번 훑는다.
- 함수 안에 존재하는 변수/함수 선언에 대한 정보를 기억 하고 있다가 실행시킨다.
- 유효범위 : 함수 블록{}안에서 유효
- 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
- 실제 코드가 끌어올려지는 것은 아니고, 자바스크립트 Parser가 내부적으로 끌어올려서 처리함
- 실제 메모리에서는 변화가 없다
호이스팅의 대상
- var 변수 선언과 함수선언문 에서만 호이스팅이 일어난다.
- var 변수/함수의 선언만 위로 끌어올려지며, 할당은 끌어올려지지 않는다.
- let/const 변수 선언과 함수표현식에서는 호이스팅이 발생하지 않는다.
console.log(“hello”); var myname = “HEEE”; // var 변수 let myname2 = “HEEE2”; // let 변수
이렇게 되어있을 때, JS Parser가 var myname을 내부적으로 끌어올린다.
foo(); foo2(); function foo() { // 함수선언문 console.log(“hello”); } var foo2 = function() { // 함수표현식 console.log(“hello2”); }
이런 코드에서는 JS Parser가 var foo2와 function foo()를 끌어올리고 나서, foo() foo2()등을 실행한다.
호이스팅은 함수선언문과 함수 표현식에서 서로 다르게 동작하기 때문에 주의해야한다.
- 변수에 할당된 함수표현식은 끌어올려지지 않기 때문에, 변수의 스코프 규칙을 그대로 따른다.
호이스팅의 우선순위
-
같은 이름의 var 변수 선언과 함수 선언에서의 호이스팅 👉 변수 선언이 함수선언보다 더 위로 끌어올려진다.
-
값이 할당되어 있지 않는 변수의 경우, 함수 선언문이 변수를 덮어쓰지만 값이 할당되어 있는 경우에는 변수가 함수선언문을 덮어쓴다.
호이스팅 사용시 주의사항
- 코드의 가독성과 유지보수를 위해 호이스팅이 일어나지 않도록한다.
- 호이스팅을 제대로 모르더라도, 함수와 변수를 가급적 코드 상단부에 선언하면 호이스팅으로 인한 스코프 꼬임현상은 방지할 수 있다.
- let/const를 사용한다.
- var를 쓰면 혼랍스럽고 쓸 모 없는 코드가 생길 수 있다. 그러면 왜 var와 호이스팅을 이해해야 하는가?
- ES6를 어디에서든 쓸 수 있으려면, 아직 시간이 더 필요하므로 ES5로 트랜스컴파일을 해야한다.
이 함수의 경우, foo()함수를 global 객체에 등록시키기 때문에(함수선언문) foo가 정상적으로 작동된다.
반면,
이 함수의 경우, var foo를 먼저 호이스팅하여 ‘undefined’인 상태에서 foo()를 실행하기 때문에, ‘foo is not a function’이라는 에러를 맞을 것이고, 이를 고치려면 할당하는 것을 함수 호출보다 위 부분에 적어주면 해결할 수 있다.
참고자료
호이스팅이란? : heejeong Kwon