프로그래밍 언어를 공부할 때 제일 먼저 배우는 것이 변수 선언이다. JS를 공부하면서 var
사용을 지양하라는 말을 들어보았고, 프론트엔드 면접을 준비하면 var
, let
,const
의 차이가 무엇인지 묻는 단골 질문도 공부했다. 그런데 왜 쓰면 안 되는데? 에 대한 질문엔 정확히 대답할 수 없었다. 지금까지는 남들이 쓰지 말라고 하니까 안 썼지만, 이제 쓰면 안 되는 정확한 이유를 알아야겠다.
let
과 const
는 ES 2015 버전부터 생겼다고 한다. 그래서 그 이전에는 어쩔 수 없이 var
키워드를 통해서 변수를 생성할 수 있었다. var
로는 부족했기 때문에 이를 보완하기 위한 더 좋은 것들이 나온 것일 텐데, 어떤 점이 개선되었을까?
var
,let
,const
는 재선언&재할당 가능 여부의 차이가 있다.var
는 함수 스코프,let
&const
는 블록 단위 스코프를 가진다.let
과const
는 Temporal Dead Zone(TDZ)이라는 속성을 가진다.
이번 포스트에서는 위의 특징들을 알아볼 것이다.
var
, let
, const
var
다음의 코드를 살펴보자.
var name = "hyun";
var name = "hyun2";
같은 이름의 변수에 다른 값을 할당했는데도 선언이 잘 된다.
var name = "hyun";
var name = "hyun2";
var name = "hyun";
console.log(name) // hyun
위 코드는 같은 이름의 변수에 값까지 똑같이 넣었다. 이 상태에서 변수를 호출해 보면 가장 마지막에 할당된 값 hyun이 나오게 된다. 즉 var
는 재할당, 재선언이 가능하다. 복잡한 프로젝트에서 재할당, 재선언이 가능한 변수를 계속해서 사용한다면 분명히 문제가 생길 것이다. 사용이 자유로운 만큼 문제의 소지는 많아진다.
let
let name = "hyun";
let name = "hyun";
var
에서 해봤던 것처럼 let
에 같은 변수명에 같은 값을 넣어보았다.
바로 에러를 뿜는다.
let
은 이미 선언한 변수를 쓸 수 없다.
let name;
name = "hyun";
name = "hyun2";
name = "hyun3";
이 코드는 에러를 내지 않는다. let
은 선언 후 재할당이 가능하기 때문이다.
const
const name;
name = "hyun";
name = "hyun2";
name = "hyun3";
위의 코드를 const
로 바꾸면 바로 에러가 난다.
const
로 변수를 선언하게 되면 할당까지 해야 에러가 나지 않는다. 즉 const는 변수를 한번 만들고 재할당을 할 수 없다.
첫 번째로는 세 가지 변수 키워드의 선언과 할당 부분에서 차이를 알아보았다. 그럼 두 번째로 언급한 scope의 차이를 알아보자.
var global = "전역";
if (gloabl == "전역"){
var global = "지역";
console.log(global); // 지역
}
전역변수를 사용하지 말라는 이야기 또한 많이 들어보았을 것이다(하면 안되는게 참 많다). 위의 코드에서는 변수 global
을 var
키워드로 선언 및 초기화하였고, if문 안에서 재선언 및 재할당하였다. if문 안의 console.log의 결과는 "지역"이다. if문 중괄호 안에 있으니까 당연한 결과다.
var global = "전역";
if (gloabl == "전역"){
var global = "지역";
console.log(global); // 지역
}
console.log(global); // 지역
그러면 if문의 중괄호 밖에서 console을 찍어 보면 어떻게 될까? if문을 벗어났으니까 "전역"이 나올 것이라고 기대하지만, 놀랍게도 결과는 여전히 "지역"이다. if문 안에서 재할당한 값이 전역 scope까지 적용된 것이다.
이유는 var
는 함수 단위 scope를 가지기 때문이다. if문은 함수가 아니기 때문에 전역공간의 변수까지 오염이 되어버렸다. var
를 쓰지 말아야 하는 이유가 점점 납득이 가기 시작한다. 프로젝트 상황에서, 많은 라인의 코드에서 이런 일이 발생한다면 끔찍하다.
let global = "전역";
if (gloabl == "전역") {
let global = "지역";
console.log(global); // 지역
}
console.log(global); // 전역
let
과 const
는 블록 단위 scope를 가지기 때문에 마음이 편안한 결과가 나온다. 지역 변수로서의 역할을 충실하게 수행해준다.
let global = "전역";
{
let global = "지역";
console.log(global); // 지역
}
console.log(global); // 전역
심지어 이렇게 중괄호만 있어도 원하는 결과를 보여준다. var
보다 훨씬 안전하게 사용할 수 있다.
var
보다는 let
, let
보다는 const
재할당이라는 키워드에 초점을 맞춰 보자. const
는 어떻게 값을 바꿀 수 있을까?
// 선언, 할당
const person = {
name: "hyun",
age: 27,
}
// 재할당이 불가능하므로 아래의 코드는 에러
person = {
name: "hyun2",
age: 20
}
// 변수의 값을 바꿔보자
person.name = "hyun2";
person.age = 20;
console.log(person)
재할당이 불가능한 것을 확인하고, 해당 부분을 주석처리 한 후 다시 실행해보면 변수 값이 잘 바뀐 것을 확인할 수 있다. person.name = "hyun2";
가 잘 동작하는 이유는 무엇일까? 변수를 재할당하지 않고 객체 내부의 값만 바꾼 것이기 때문이다.
const person = [{
name: "hyun",
age: 27,
}]
person.push({name: "hyun3", age: 34});
console.log(person) // [ { name: 'hyun', age: 27 }, { name: 'hyun3', age: 34 } ]
이 또한 잘 동작한다! const
는 재할당만 금지된다. 객체, 배열의 레퍼런스 값을 조작할 때는 문제가 없다는 뜻이다. var
이나 let
을 사용해서 변수를 재할당하지 않아도, const
로도 변수 내부의 값을 변경할 수 있으므로 제일 안전한 const
를 쓰는 것을 권장한다고 한다.
키워드 | 재선언 | 재할당 | scope |
---|---|---|---|
var | 가능 | 가능 | 함수 |
let | 불가능 | 가능 | 블럭 |
const | 불가능 | 불가능 | 블럭 |