호이스팅(hoisting)이란 '끌어올리다'라는 의미의 hoist + ing를 붙여 만들어졌으며 의미 그대로 끌어올리는 행위로 작동한다. 주로 var로 선언된 변수의 선언문을 코드의 최상단으로 끌어올인다. (변수 정보를 수집하는 과정을 이해하기 쉬운 방법으로 대체한 가상의 개념으로, 자바스크립트 엔진이 실제로 끌어올리지는 않지만 편의상 끌어올린 것으로 간주된다.)
실행컨텍스트에 담기는 LexicalEnvironment의 내부는 environmenRecord와 outer-EnvironmenReference로 구성되는데 environmenRecord는 호이스팅과 관련이 있다.
식별자 정보를 수집하는 과정을 마쳐도 코드가 실행되기 전이기 때문에 실행컨텍스트가 관여한 코드들은 실행되기 전의 상태이다. (실행전이지만 수집과정을 거쳤기 때문에 해당 환경의 변수명을 모두 알고 있다.)
*변수명과 함수 전체의 정보를 위로 끌어올리고 할당과정은 원래 자리에 남겨둔다.
function a() {
console.log(b); // ƒ b() { }
var b = 111; // ← 수집대상 1
console.log(b); // 111
function b() { // ← 수집대상 2
console.log(b) // 111
}
}
a();
a함수를 실행하는 순간 a 함수의 실행 컨텍스트가 생성된다. (변수명과 함수가 위로 끌어올려진다.)
위의 코드에서는 수집대상 1과 2를 순서대로 끌어올리고 다음과 같은 형태로 동작한다.
// 호이스팅 완료 (실제 변환과정이 아닌 쉽게 이해하기 위한 예시 코드)
function a() {
var b;
function b() {};
console.log(b); // ƒ b() { }
b = 111;
console.log(b); // 111
console.log(b); // 111
}
a();
함수 선언문(function declaration)
은 function 정의부만 존재하고 별도의 할당 명령이 없는 것을 의미하고, 함수 표현식(function expression)
은 정의한 function을 별도의 변수에 할당하는 것을 말한다.
console.log(sum(1, 2)); // 3
console.log(multiply(3, 4)); // Uncaught TypeError: multiply is not a function
// 1. 함수 선언문
function sum(a, b) {
return a + b;
}
// 2. 함수 표현식
var multiply = function (a, b) {
return a * b;
}
함수가 선언된 후에야 호출 할 수 있기 때문에 예시에서 함수 표현식으로 정의된 multiply(3, 4)를 호출하면 'Uncaught TypeError' 에러가 뜬다. 호이스팅 된 상황을 아래의 코드로 재현해보면,
// 호이스팅 완료
/* 함수 선언문 전체가 끌어올려진다.*/
function sum(a, b) {
return a + b;
}
/* 함수 표현식의 변수만 끌어올려진다. */
var multiply;
console.log(sum(1, 2)); // 3
/* 변수 multiply만 선언되었기 때문에 TypeError가 발생한다. */
console.log(multiply(3, 4)); // Uncaught TypeError: multiply is not a function
multiply = function (a, b) {
return a * b;
}
*다수의 개발자들이 협업할 때, 각각의 개발자가 함수 선언문을 이용해서 동일한 함수명으로 개발하였다면 호이스팅으로 인한 문제가 발생한다. (코드가 덮어씌워지는 문제가 발생한다.) 따라서 여러명이 협업할 때 함수는 함수 표현식을 이용하여 개발하도록 해야한다.
참고 : 코어 자바스크립트(정재남)