Skip to main content

2021년 5월

2021-05-25#

호이스팅(Hoisting)#


호이스팅 개념#

  • 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.

호이스팅 이란#

  • 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다.
  • 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
  • 함 안에 존재하는 변수/함수 선언에 대한 정보를 기억하고 있다가 실행시킨다.
  • 유효 범위: 함수 블록 {} 안에서 유효
  • 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
  • 실제로 코드가 끌어 올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다.
  • 실제 메모리에서는 변화가 없다.

호이스팅의 대상#

  • var 변수, 함수 선언문 에서 호이스팅이 일어난다.
  • let/const변수 와 함수 표현식은 호이스팅이 일어나지 않는다.

var 변수와 let 변수에서의 호이스팅#

console.log(myName); // undefined
console.log(myName2); // ERROR
var myName = '철수';
let myName2 = '영희';
console.log(myName); // 철수
console.log(myName2); // 영희

위 코드를 보면 var 변수 myName은 호이스팅이 일어나 선언 위치보다 위에서 호출해도 사용이 가능 한 것을 볼 수 있다. 하지만 let 변수 myName2는 호이스팅이 일어나 에러가 발생한다.

함수 선언문과 함수 표현식에서의 호이스팅#

hello(); // hello
hello2(); // TypeError
function hello() {
console.log('hello');
}
var hello2 = function () {
console.log('hello');
}; // `함수 표현식`
hello(); // hello
hello2(); // hello

위 코드에서 TypeError 가 발생한 이유는 var 변수 Hello2는 호이스팅이 일어났지만 함수 표현식 이 호이스팅이 발생하지 않아 위에서 Hello2의 상태undefined 상태이기 때문에 TypeError가 발생한 것이다.

호이스팅의 우선 순위#

자바스크립트 엔진 실행 과정#

  1. 자바스크립트 첫 실행을 위한 main() 함수의 Global Scope (window) 영역을 Heap에 생성
  2. var 변수를 찾아서 Global Scope (window) 영역에 var 적재 (이때 값이 할당되지는 않는다.)
  3. 함수 선언문을 찾아서 Global Scope (window) 영역에 적재
  4. 함수 적재 시엔 함수의 바이트코드(blob)에 대한 포인터 값을 함께 적재합니다.

var 변수가 함수 선언문 보다 위로 끌어 올려진다.#

var Hello = 'Hi';
function Hello() {
console.log('Hello');
}
function Hello2() {
console.log('Hello2');
}
var Hello2 = 'Hi2';
console.log(typeof Hello); // string
console.log(typeof Hello2); // string

위 코드를 보면 함수명과 변수명이 동일하다 하지만 밑에서 타입을 확인해보면 string으로 나타나는 것을 확인할 수 있다. 그 이유는 var 변수가 함수 선언문 보다 더 위로 끌어올려지기 때문이다.

값이 할당되지 않은 변수의 경우#

console.log(typeof Hello); // function
console.log(typeof Hello2); // function
var Hello = 'Hi';
var Hello2;
function Hello() {
console.log('Hello');
}
function Hello2() {
console.log('Hello2');
}
console.log(typeof Hello); // string
console.log(typeof Hello2); // function

위 코드를 보면 위에서 typeof를 통해 타입을 확인해보면 fuction으로 나타나는 것을 볼 수 있다. 그 이유는 함수 표현식은 Global Scope 영역에 적재될 때 바이트코드(blob)에 대한 포인터 값을 함께 적재하고 var 변수는 값이 할당되지 않기 때문에 undefined 상태가 된다. 그래서 undefined 가 아닌 fuction이 나오는 것을 볼 수 있다.

함수 선언문이 호출보다 위에 있을 경우#

function printName() {
var inner = function () {
return 'inner value';
};
var result = inner();
console.log('name is ' + result); // name is inner value
}
printName(); // 정상실행

함수 선언문이 호출보다 아래에 있을 경우#

function printName() {
var result = inner(); // 함수 호출 시점
console.log(typeof inner); // function
console.log('name is ' + result); // name is inner value
function inner() {
// 함수 선언문
return 'inner value';
}
}
printName(); // 정상실행

함수 호출이 함수 선언문 보다 위에서 일어나지만 호이스팅이 발생해 정상적으로 작동하는 것을 볼 수 있다.

함수 표현식의 선언이 호출보다 아래에 있을 경우#

function printName() {
console.log(inner); // undefined
var result = inner(); // ERROR!! 함수 호출
console.log('name is ' + result);
var inner = function () {
// 함수 표현식
return 'inner value';
};
}
printName(); // TypeError 실행불가

함수 호출 시점보다 함수 표현식이 더 아래에 있음으로 함수 호출 시점 inner 는 정의되어 있지 않은 상태이다 그러므로 Error 가 발생한다.

호이스팅 사용 시 주의 사항#

  • 코드의 가독성과 유지 보수를 위해 호이스팅이 일어나지 않도록 한다.

  • 호이스팅을 제대로 모르더라도 함수와 변수를 가급적 코드 상단부에서 선언하면, 호이스팅으로 인한 스코프 꼬임 현상은 방지할 수 있다.

  • let/const를 사용한다.

  • var를 쓰면 혼란스럽고 쓸모없는 코드가 생길 수 있다. 그럼 왜 var와 호이스팅을 이해해야 할까?

  • ES6를 어디에서든 쓸 수 있으려면 아직 시간이 더 필요하므로 ES5로 트랜스 컴파일을 해야 한다. 따라서 아직은 var가 어떻게 동작하는지 이해하고 있어야 한다.

출처:https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html