호이스팅에 대한 정의를 알기 전에 var
에 대해 먼저 알아야합니다.
초기 자바스크립트 변수 선언 방식입니다. 2015년도에 자바스크립트가 ES6로 업그레이드 되면서 let
과 const
가 나왔습니다. ES6 이후에는 잘 사용하지 않지만 오래된 자바스크립트에서 종종 볼 수 있습니다. 그렇다면 최근에 사용되지 않는 이유는 무엇일까요?
var name = "lemon";
console.log(name); // "lemon"
var name = "Mike";
console.log(name); // "Mike"
변수는 주민등록번호 같은것이기 때문에 다시 선언할 수 없어야합니다.
하지만 var
은 변수를 다시 선언해도 아무런 에러가 뜨지 않습니다.
위의 코드를 let
으로 바꿔서 똑같이 작성해보면
let name = "lemon";
console.log(name);
let name = "Mike";
console.log(name);
name
은 이미 선언됐다는 에러 페이지가 뜹니다. 이게 정상적인 로직입니다.
console.log(name); // undefined ⚠️원래는 에러가 떠야합니다.
var name = "Mike";
console.log(name); // "Mike"
자바스크립트는 인터프리터(코드를 한 줄씩 읽어 내려가며 실행하는 프로그램)언어 이기 때문에 코드를 항상 아래에서 위로 읽습니다. 1번째줄 입장에서 두번째 줄을 아직 안갔으니 name
은 없는 변수여야 합니다. name
이 선언되기 전에 찾게 되면 ReferenceError(참조에러 : 초기화 전에 name에 접근할 수 없음)가 나와야합니다.
위의 예제를 let
으로 바꾼다면 정상적으로 에러가 발생합니다.
console.log(name); // ReferenceError
let name = "Mike";
var
이 이런 말이 안되는 로직이 가능한 이유는 호이스팅(hoisting)이라는 개념 때문입니다. 선언된 변수들이 코드상 실제로 이동하진 않지만 최상위로 끌어올려진 것처럼 동작하는 것을 호이스팅이라고 합니다.
👇🏻 위의 예제를 호이스팅의 개념으로 정리해서 보자면 이렇습니다.
var name; → 선언된 변수가 최상위로 올라왔다.
console.log(name); // undefined
name = "Mike"; → 그러나 값은 올라가지 못한다. 따라서 값은 할당해주어야 한다.
console.log(name); // Mike
함수가 실행되기 전에 선언된 변수와 함수를 가져가서 메모리에 기억해둡니다. 이게 무슨 뜻이냐면 자바스크립트가 실행될 때 어떤 변수랑 함수가 있는지부터 싹 훑어서 기억해두고 후에 누군가 name
라는 변수를 부르면 자바스크립트가 기억해둔 변수랑 함수에서 찾아주는 것을 말합니다. 그렇지만 변수 할당된 값은 찾지 못해서 undefined
가 나오는 걸 볼 수 있습니다.
undefined
가 나타나는 이유var
로 선언한 변수의 경우 호이스팅 시 변수의 값을 undefined
로 초기화합니다. 변수를 선언하기 전에 사용할 수 있지만 값은 나오지 않는 이유입니다.
✍🏻 호이스팅을 설명할 땐 주로 "변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는" 것으로 말하곤 합니다.
TDZ 영역에 있는 변수들은 사용할 수 없습니다. let
과 const
는 TDZ의 영향을 받습니다. 일시적으로 죽은 공간이다라는 뜻입니다.
값을 할당하기 전에는 사용할 수 없도록 죽은 공간으로 만드는 것입니다. TDZ로 잠재적인 버그를 줄일 수 있습니다.
🖥️ “ name
이 호이스팅으로 기억 되긴했지만 name
선언문이 나오기 전까진 접근할 수 없어! 여기는 일시적으로 죽은 zone이야! ”
let
의 호이스팅호이스팅은 함수 내부에서도 일어납니다. 스코프 단위로 일어나기 때문입니다.
let age = 28;
function showAge() {
console.log(age); ⇒ Temporal Death Zon
let age = 20; // ReferenceError
}
showAge();
전역변수는 블락 { } 밖에서 선언을 한 변수로 어디서든 쓰일 수 있습니다.
지역변수는 블락 { } 안에서 선언된 변수로 블락 안에서만 쓸 수 있습니다.
블록 스코프는 지역변수입니다. 모든 코드 블럭 내에서 선언된 변수는 코드블럭 내에서만 유효하면 외부에서는 접근 할 수 없습니다.
( 코드 블락 : 함수, if문, for문, while문, try/catch 문 등을 의미 )
function add() {
// Block-level Scope
}
if() {
// Block-level Scope
}
for(let i=0;i<10;i++) {
// Block-level Scope
}
var
은 함수(function)안에서 쓴것만 지역변수로 올려두고, 나머지 for문, if문 등등에서 쓰인것은 다 전역변수로 사용합니다.
👇🏻 유일하게 벗어날 수 없는 스코프가 함수(function)입니다.
function add(num1, num2){
var result = num1 + num2;
}
add(2,3);
console.log(result); // Uncaught SyntaxError 에러 발생
👇🏻 if문 안에서 var
로 선언된 변수는 if문 밖에서도 사용이 가능합니다.
const age = 30;
if(age<19){
var txt = '성인';
}
console.log(txt); // '성인'
for(var i = 1; i<5; i++){
console.log(i)
}
console.log(i) // 1 2 3 4 5
👇🏻 let
으로 바꾼다면?
for(let i = 1; i<5; i++){
console.log(i)
}
console.log(i)
i는 선언되지않았다는 에러메세지가 나타납니다.
var
은 초기 자바스크립트 변수 선언 방식입니다.var
의 문제점const
와 let
은 블록 스코프(block-scoped)입니다.var
은 함수 스코프(function-scoped)입니다.var
함수를 제외하고는 스코프를 벗어나서도 변수를 사용할 수 있습니다.const
와 let
도 호이스팅을 하지만 Temporal Death Zon(TDZ)이 있어서 선언 전의 변수를 사용할 수 없습니다.