Front-end Developer

0%

변수 호이스팅

변수 호이스팅

변수 선언: 변수를 생성하는 것. 자바스크립트 엔진은 선언-초기화의 2단계에 걸쳐 변수 선언을 수행한다.

  • 선언 단계: 변수 이름을 등록하여 자바스크립트 엔진에 변수의 존재를 알린다.
  • 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당.
1
2
console.log(score); //undefined
var score; //변수 선언문

보통 자바스크립트 코드는 한 줄씩 순차적으로 실행되기 때문에 console.log(score);가 먼저 실행된 후 순차적으로 코드가 실행된다. 그런데 console.log(score);가 실행되는 시점에는 변수 선언이 아직 실행되지 않았기 때문에 식별자를 찾아서 값을 참조하려고 했는데 찾을 수 없는 typeError가 발생해야 한다. 그런데 코드를 실행해보면 typeError 대신 undefined라는 값을 출력한다.

자바스크립트 엔진은 런타임 이전에 모든 선언문(변수 선언문, 함수 선언문 등)을 소스 코드에서 찾아내서 먼저 실행한다. 따라서 선언문이 어느 위치에 있던지 상관없이 런타임 이전에 먼저 실행된다. 그렇기 때문에 변수 선언 이전에 값을 참조할 수 있다. 이렇게 변수 선언문이 코드의 선두로 끌어올려진 것 처럼 동작하는 것이 변수 호이스팅이다.

함수 호이스팅

  • 함수 선언문: 함수 선언문 이전에 호출가능 - 함수 호이스팅
  • 함수 표현식: 함수 선언문 이전에 호출불가 - 변수 호이스팅

함수 호이스팅
모든 선언문은 런타임 이전에 실행되기 때문에 함수 선언문도 런타임 이전에 실행된다. 함수는 런타임 이전에 함수 객체를 생성하고 함수 객체와 동일한 식별자에 할당을 완료한다. 따라서 함수 선언문 이전에 값을 참조하거나 호출할 수 있다.

1
2
3
4
5
6
console.dir(add); //f add(x,y)
console.log(add(2, 5)); //7

function add(x, y) {
return x + y;
}

변수 호이스팅
함수 표현식은 변수 할당문의 값이 함수 리터럴인 문이다. 따라서 변수 선언문과 변수 할당문의 축약 표현과 동일하게 동작한다. 따라서 함수 표현식을 표현식 이전에 호출하면 typeError, 참조하면 undefined가 발생한다. 변수 할당문의 값은 할당문이 실행되는 런타임에 평가되기 때문에 런타임 때 비로소 평가되어 함수 객체가 된다.

1
2
3
4
5
6
console.dir(sub); //undefined
console.log(sub(2, 5)); //typeError

var sub = function (x, y) {
return x - y;
};

var 키워드의 변수 호이스팅
var 키워드는 변수 호이스팅에 의해 변수 선언문 이전에 참조 가능하다.

1
2
3
4
5
6
7
8
9
// var 키워드로 선언한 변수
console.log(foo); // undefined 런타임 이전에 참조가능
//선언과 초기화가 런타임 이전에 동시에 이루어진다.

var foo;
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

let키워드의 변수 호이스팅
let 키워드는 변수 참조에러가 발생해서 변수 호이스팅이 발생하지 않는 것처럼 보이지만, 변수 호이스팅이 발생한다.

1
2
3
4
5
6
7
8
9
console.log(foo); // ReferenceError: foo is not defined
//런타임 이전에 선언 단계만 실행된다.
//변수 초기화가 아직 이루어지지 않았으므로 참조가 불가하다.

let foo; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

var와 let의 차이점
var와 let 모두 런타임 이전에 암묵적으로 선언단계가 실행된다. 그런데 var는 런타임 이전에 선언을 하고 undefined라는 값으로 초기화하는 단계까지 진행된다. 따라서 런타임 이전에 값을 호출하면 undefined라는 값이 출력되는 것이다. 그러나 let은 런타임 이전에 선언 단계만 실행된다. 초기화는 런타임 때 변수 선언문을 만났을 때 이루어지기 때문에 스코프의 시작 지점부터 변수 선언문을 만나 초기화가 이루어지는 단계까지는 변수에 접근하려고 해도 참조 에러가 발생하게 되는 것이다. 이를 일시적 사각지대라고 한다.