변수의 선언문이 가장 먼저 수행되는 것
호이스팅이란 변수의 선언문 부분이 Scope의 최상단으로 끌어올려져 수행되는 자바스크립트의 메커니즘이다.
선언문이라 하면 대표적으로 var
, let
, const
, function
, function*
, class
키워드로 시작되는 코드들을 말한다.
예를들어 var name = 'value'
코드는 ,
var name
과 a = 'value'
로 나눌 수 있다.
호이스팅이 발생하게되면 선언문인 var name
부분만 최상단에서 먼저 수행하게 된다.
이는 변수가 선언되기 전에도 에러없이 호출이 가능해지는 결과를 만든다.
console.log(a); // undefined
console.log(b); // undefined
console.log(c); // undefined
console.log(d); // undefined
console.log(e); // function e () { }
var a = 1;
var b = 2;
var c = 3;
var d = function () {}
function e () { }
위의코드는 호이스팅이 발생하여 실제로 아래순서로 동작한다.
var a;
var b;
var c;
var d;
function e () { console.log('function d'); }
console.log(a); // undefined
console.log(b); // undefined
console.log(c); // undefined
console.log(d); // undefined
console.log(e); // function e () { }
a = 1;
b = 2;
c = 3;
e = function () {}
변수는 var
, let/const
키워드를 이용하여 선언할 수 있다.
이 둘은 다양한 차이점들이 있지만, 호이스팅측면에서의 차이점은 let/const
변수는 호이스팅이 발생하더라도 참조가 불가능하다는 점이다.
console.log(a); // undefined
console.log(b); // Uncaught ReferenceError: Cannot access 'b' before initialization
console.log(c); // Uncaught ReferenceError: Cannot access 'c' before initialization
var a = 1;
let b = 2;
const c = 3;
이유를 알아보기전에, 변수에 값이 할당되는 과정을 알고가야한다.
변수는 선언되어 값이 할당되기까지 3단계를 거친다.
- 선언 (메모리영역 할당)
- 초기화 (할당된 메모리영역 초기화)
- 값의 대입 (메모리영역에 값을 저장)
var
와 let/const
키워드는 변수의 초기화시점이 다르다는 차이가있다.
var a = 3;
var a
선언문에서 변수가 선언되고 초기화된다. (선언, 초기화)
a = 3
대입문에서 값의 대입이 이루어진다. (할당)
let /*const*/ b = 5
let b
, const b
변수를 선언한다. (선언)
b = 3
에서 변수를 초기화한 후 할당된다. (초기화, 할당)
javascript에서 초기화를 하지 않은 변수는 참조가 불가능하기때문에, 값을 할당되는 과정에서 초기화가 이루어지는 let/const
키워드의 변수들은 참조가 불가능하게된다.
변수가 선언되어 초기화되기까지를 일시적 사각지대라고 부른다.
즉, 일시적 사각지대(TDZ) 구간에 있는 변수는 참조가 불가능하다.
함수는 이전 포스팅에서 다뤘듯이, 함수표현식
과 함수선언문
으로 정의할 수 있다.
console.log(a); // function a() {}
console.log(b);// undefined
function a () {}
var b = function () {};
함수표현식
은 변수의 호이스팅과 동일하게 동작한다.
따라서 선언문인 var b
와 대입문인 b = function () {};
로 나뉘어지고, 호이스팅으로 인해 선언문이 먼저 선언된다.
위 코드에서 함수표현식
으로 정의한 b는 undefined
로 참조가 된다.
함수선언문
은 선언, 초기화 및 할당까지 모두 한번에 이루어진다.
따라서 함수선언문
으로 정의한 a는 실제값인 funciton a() {}
가 참조되고 있다.
반면에 함수표현식
은 선언문인 var b
와, 표현식인 b = function () {};
로 나뉘어집니다.\
따라서 var b
가 먼저 동작하여 선언, 초기화 까지만 이루어지고, undefined
로 참조가 됩니다.
변수의 선언, 초기화, 할당이 어떤시점이 이루어지냐를 파악하는게 핵심이다.