변수를 선언하면 변수 호이스팅에 의해 변수 선언문이 스코프의 선두로 끌어 올려진 것처럼 동작한다.
// 이 시점에는 변수 호이스팅에 의해 이미 foo 변수가 선언되었다.
// 변수 foo는 undefined로 초기화 된다.
console.log(foo);
// 변수에 값을 할당
foo = 123;
console.log(foo);
// 변수 선언은 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로
// 실행된다.
var foo;
변수 선언문 이전에 변수를 참조하는 것은 변수 호이스팅에 의해 에러를 발생시키지는 않지만 프로그램의 흐름상 맞지 않을뿐더러 가독성을 떨어뜨리고 오류를 발생시킬 여지를 남긴다.
var 키워드로 선언한 변수와 달리 let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작한다.
console.log(bar); // ReferenceError: bar is not defined
let bar;
다만 let 키워드로 선언한 변수는 "선언 단계"와 "초기화 단계"가 분리되어 진행된다. 즉, 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계가 먼저 실행되지만 초기화 단계는 변수 선언문에 도달했을 때 실행된다.
// 런타임 이전에 선언 단계가 실행된다. 아직 변수가 초기화되지 않았다.
// 초기화 이전에 일시적 사각지대에서는 변수를 참조 할 수 없다.
console.log(foo); // ReferenceError: foo is not defined
let foo; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(foo); // undefined
foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1
결국 let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 보이지만 실제로는 그렇지 않다.

위의 예시와 마찬가지로 let, const 같은 변수를 선언하고 호출하는 과정이 아니라 호출이 선언보다 앞선 경우에는 Refercence 에러를 발생시킨다. 그 이유는 var는 선언 단계에 undefiend를 자동으로 초기화 하지만 let, const 같은 경우에는 선언 단계와 초기화 단계가 나뉘어 있다. 런타임 이전 단계에 선언이 이루어지고 런타임 단계에 초기화가 이루어지기 때문에 일시적 사각지대가 발생하여 Refercence 에러를 발생 시키는 것이다.
이와 같은 사례는 변수 뿐만이 아닌 function, class 같은 경우에서도 적용된다. 단 ES6에서 도입된 const, let, class를 사용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다.