ES5까지의 자바스크립트에서는 var를 이용해서 변수를 정의했고 그게 유일한 방법이었다.
ES6에서 const
와 let
을 이용하는 새로운 변수 정의 방법이 생겼다. 그 이유에는 var가 가진 문제들이 있었기 때문이다.
var는 어떠한 문제를 가지고 있었는가?
var가 가진 문제
1) 함수 스코프
var로 정의된 변수는 함수 스코프
를 가진다. 스코프란 변수가 사용될 수 있는 영역을 말한다.
function example(){
var i=1;
}
console.log(i)//참조에러
위 코드처럼 스코프를 벗어나서 변수를 사용하면 에러가 난다.
function example1(){
i=1;//var 키워드 없이 변수를 정의하면 전역변수가 된다.
}
function example2(){
console.log(i);
}
example1();
example2();//1이 출력됨
var 변수를 함수가 아닌 프로그램 바깥에 정의하면 전역변수가 되는데, 이는 프로그램 전체를 감싸는 하나의 함수가 있다고 생각하면 이해가 쉽다.
특이한 점은, 함수 안에서 var 키워드를 사용하지 않고 변수에 값을 할당하면 그 변수는 전역 변수가 된다.
for( var i=0;i<10; i++){
console.log(i);
}
console.log(i)//10
var는 함수 스코프이기에 for 반복문에서 정의된 변수가 반복문이 끝난 이후에도 계속 남는 문제점이 있다.
2) 호이스팅
var로 정의된 변수는 그 변수가 속한 스코프의 최상단으로 끌어올려진다.
console.log(myVar);//undefined
var myVar=1;
변수가 정의된 시점보다 먼저 변수 사용. 그런데 undefined가 출력된다. 이는 해당 변수의 정의가 위쪽으로 끌어올려졌기 때문이다.
var myVar=undefined;
console.log(myVar);//undefined
myVar=1;
위는 호이스팅의 결과
console.log(myVar);//undefined
myVar=2;
console.log(myVar);//2
var myVar=1;
=> 변수의 정의만 끌어올려지고 값은 원래 정의했던 위치에서 할당된다.특이하게도 다음처럼 변수가 정의된 곳 위에서 값을 할당할 수도 있다.
버그처럼 보이는 위 코드가 에러없이 사용될 수 있는 것은 단점이다. 호이스팅은 직관적이지 않고 보통의 프로그래밍 언어에서는 찾아보기 힘든 성질이다.
3) var변수는 재정의가 가능하다
var myVar=1;
var myVar=2;
변수를 정의한다는 것은 이전에 없던 변수를 생성한다는 의미로 통용된다. 따라서 위 코드가 에러없이 사용될 수 있다는 것은 직관적이지 않고 버그로 이어질 수 있다.
1)블록스코프
함수 스코프의 단점 대부분이 블록스코프에는 없다.
if(true){
const i=0;
}
console.log(i)//참조에러
블록스코프에서 if문의 블록 안에서 정의된 변수는 if문을 벗어나면 참조할 수 없다.
let foo='bar1';
console.log(foo);//bar1
if(true){
let foo='bar2';
console.log(foo);//bar2
}
console.log(foo);//bar1을 출력
2) 호이스팅
console.log(foo);//참조에러
const foo=1;
똑같은 경우에 var는 에러가 발생하지 않는다. 따라서 const,let으로 정의된 변수는 호이스팅되지 않는다고 생각하기 쉽다. 그러나!! const,let으로 정의된 변수도 호이스팅된다.
다만 변수가 정의된 위치와 호이스팅된 위치 사이에서 변수를 사용하려고 하면 에러가 발생한다. 이 구간을 임시적 사각지대(TDZ)
라고 한다.
임시적 사각지대에서 변수를 사용하지 못한다면 호이스팅의 역할은 무엇인가?
const foo=1;//2
{
console.log(foo);//참조에러 3
const foo=2;//1
}
1번 변수가 호이스팅되지 않았다면 참조 에러는 발생하지 않고 2번 변수의 값이 출력될 것이다. 1번 변수의 호이스팅 때문에 3번 변수는 1번 변수를 참조하게 된다. 그리고 1번 변수를 참조했지만 임시적 사각지대여서 에러가 발생한다.
3)const로 정의된 변수만 재할당 불가능하게 만든다.
const로 정의된 변수는 재할당이 불가능하다. 반대로 let,var로 정의된 변수는 재할당할 수 있다.
참고: 실전리액트프로그래밍