“자바스크립트에서 함수 및 변수 선언이 코드 순서상 먼저 일어나지 않아도 실행할 수 있는 것”
호이스팅은 코드를 실행하기 전
변수선언/함수선언
을 해당 스코프의 최상단으로 끌어올리는 것이 아니다.
변수선언/함수선언
이 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상을 말한다.**
이와 같은 자바스크립트에서의 호이스팅이란 특징으로 인해, javascript에서 변수는 사용된 이후 선언 될 수 있다. (==변수를 사용한 후 선언 할 수 있다)
두가지 예시를 들어보자.
$(document).ready(function(){
var x;
x = 5;
console.log(x);
});
⇒ 변수를 선언 후 변수에 값을 저장한 케이스. 보기에도 문제가 없어보이고 실행 결과도 문제가 없다.
$(document).ready(function(){
x = 5;
console.log(x);
var x;
});
⇒ 변수에 값을 저장/사용 후 선언한 케이스.
에러없이 정상 결과가 나온 이유는 바로 hoisting 때문이다.
(var x;
부분(변수 선언부)을 현재 scope에서 최상단으로 끌어올렸기 때문)
💡 자바스크립트는 선언부만 hoisting할 뿐, 초기화부분까지 hoisting하지않는다.
$(document).ready(function(){
console.log(x);
console.log(y);
var x = 5;
});
x 는 'undefined'를 콘솔에 출력하고 있고,y는undefined Error 을 던지고 있다.
var x 부분은 hoisting 되었지만 초기화(=5)부분은 호이스팅되지 않았기 때문이다.
y는 스코프내에 선언되어 있지 않으므로 Error 를 뱉고 있다.
[결론]
예상치 못한 hoisting 동작으로 인한 에러를 피하기 위해 변수 선언 및 초기화는 최상단에서 해주자.
JavaScript는 초기화를 제외한 선언만 호이스팅한다. 변수를 먼저 사용하고 그 후에 선언 및 초기화가 나타나면, 사용하는 시점의 변수는 기본 초기화 상태(var
선언 시 undefined
, 그 외에는 초기화하지 않음)이다. 예를 들어,
console.log(num); // 호이스팅한 var 선언으로 인해 undefined 출력
var num; // 선언
num = 6; // 초기화
반면, 다음 예제는 선언 없이 초기화만 존재한다. 따라서 호이스팅도 없고, 변수를 읽으려는 시도에서는 ReferenceError
예외가 발생한다.
console.log(num); // ReferenceError
num = 6; // 초기화
let
과 const
로 선언한 변수도 호이스팅 대상이지만, var
와 달리 호이스팅 시 undefined
로 변수를 초기화하지는 않는다. 따라서 변수의 초기화를 수행하기 전에 읽는 코드가 먼저 나타나면 예외가 발생한다.
하나의 특별한 목적의 작업을 수행하도록 설계된 독립적인 블록을 의미한다.
이러한 함수는 필요할 때마다 호출하여 해당 작업을 반복해서 수행할 수 있다.
자바스크립트에서 함수의 정의는 function 키워드로 시작되며, 다음과 같은 구성요소를 가진다.
변수는 3단계에 걸쳐 생성된다.
변수를 실행 컨텍스트의 변수 객체에 등록한다.이 변수 객체는 스코프가 참조하는 대상이 된다.
💡 var, let, const를 통해 선언
변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.이 단계에서 변수는 undefined로 초기화 된다.
undefined로 초기화된 변수에 실제 값을 할당한다.
var 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이뤄진다. 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화한다.
따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다.
let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다. 즉, 스코프에 변수를 등록(선언 단계)하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후) 이뤄진다. 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다. 이는 아직 변수가 초기화되지 않았기 때문이다. 즉, 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문이다. 따라서 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다. 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 ‘일시적 사각지대(Temporal Dead Zone; TDZ)’라고 부른다.
변수를 선언할 때 변수값이 고정이라면 const로 선언,
변수값이 변동될 가능성이 있으면 let으로 선언하는 편이 좋다.