var, let, 그리고 const
시작하며
javaScript 를 공부하다보면 자연스레 이 세가지 키워드에 대해 알게 된다.
let 과 const를 알기 전까지만해도 javaScript는 var 뿐만으로 돌아가는 신비한 언어체계를 가지고있었다.
하지만 현재 공식적으로 const 와 let 키워드가 추가되었고, 이 둘의 사용을 권장하고있다.
이 타입은 무엇이며, 어째서 기존의 방식을 버리고 이 새로운 선언 방식을 권장하는가?
이를 알기 위해서는 변수의 선언과 호이스팅, 스코프에 대해 알아야할 필요가 있다.
변수의 선언
변수의 선언은 var
, let
, const
로 할 수 있으며 이중 let 과 const는 ES6에서 추가되었다.
위의 세가지 키워드를 간단하게 설명하자면 다음과 같다.
var
: 재선언 가능, 재할당 가능
let
: 재선언 불가능, 재할당 가능
const
: 재선언 불가능, 재할당 불가능
var a = 1;
var a = 2;
a = 6;
// var 키워드는 재선언과 재할당에 있어서 전혀 문제없이 동작이 가능하다.
let a = 1;
let a = 2; // => Uncaught SyntaxError: Identifier 'a' has already been declared
// let 키워드를 통한 선언은 재선언이 불가능하며 재선언시 구문오류를 발생시킨다.
a = 5;
// 재할당은 문제없이 동작한다.
const a = 5;
const a = 3; // => Uncaught SyntaxError: Identifier 'a' has already been declared
// const 키워드 또한 let 과 동일하게 재선언시 구문오류를 발생시킨다.
a = 6; // => Uncaught TypeError: Assignment to constant variable.
// const 키워드는 재할당도 불가능하기 때문에 이경우 타입오류를 발생시킨다.
let은 재할당이 가능한 점을 꼽아 var를 대체하는 키워드로 사용되고있으며
const는 재할당도 불가능한 점을 이용하여 변경되지않는 상수 (constant) 의 역할로 사용되고있다.
const의 이런 특징은 함수의 생성에도 큰 도움을 주게되는데 이 내용은 추후에 작성하도록 하겠다.
특징이 명확한 만큼 사용하기 나름일 것으로 보이지만
var 의 사용을 지양하고 let 과 const를 권장하는것은 그만한 이유가 있다.
호이스팅
var 의 가장 큰 문제점은 무엇일까?
그것은 바로 호이스팅일 것이다.
호이스팅은 끌어올리다 라는 뜻으로.
javaScript는 선언된 var 변수를 최상단으로 끌어올린다.
console.log(some_data);
var some_data = 'heeey';
console.log(some_data);
위와 같은 코드를 작성하여 실행할 경우
var some_data; // 변수선언문을 최상단으로 끌어올린다.
console.log(some_data); // 변수선언문을 최상단으로 끌어올렸으므로 에러는 발생하지않지만
// 값 할당이 되지 않았기 때문에 undefined가 출력된다.
some_data = 'heeey'
console.log(some_data);
위와같이 변수 선언문을 최상단으로 끌어올리기때문에 오류없이 작동이 된다.
어떻게 보자면 편리함을 주는 것같지만 이러한 특징은 규모가 커지는 프로젝트에서 사용할 경우 디버그를 매우매우 어렵게 만든다는 치명적인 단점이 있다.
그렇다면 let과 const는 var 와 정확히 어떤 부분에서 다른 것일까??
스코프
var 는 function scope를 가진다.
이는 함수 단위의 유효범위를 가진다는 것이다.
console.log(a); // Uncaught ReferenceError: a is not defined
testFunc();
function testFunc() {
console.log(a) // undefined
var a = 1;
console.log(a) // 1
}
위 코드에서 a 라는 변수는 testFunc 안에 선언되어있다.
var 는 함수 단위의 유효범위를 가지므로 1번째 줄의 a 로그는 오류를 발생시킨다.
testFunc 내부에서는 정상적으로 a를 호출하는 것을 볼 수 있다.
재밌는 점은 앞서 언급한 호이스팅은 함수 선언에도 적용이 된다는 점이다.
따라서 위 코드의 testFunc 은 선언문보다 호출이 먼저임에도 불구하고 정상적으로 실행이 된다.
let 과 const는 block scope를 가진다.
이는 블록 단위의 유효범위를 가진다는 것인데,
이 블록이란 중괄호 {} 로 이루어진 범위를 말한다.
console.log(a); // Uncaught ReferenceError: a is not defined
testFunc();
function testFunc() {
if (true) {
console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 1;
console.log(a) // 1
}
console.log(a) // Uncaught ReferenceError: a is not defined
}
let 으로 선언한 변수는 앞서 var 변수가 보여줬던 호이스팅이 발생하지 않기 때문에 6번째 줄의 a 출력문제에서 참조오류를 발생시켰다.
그리고 10번째 줄에서또한 참조오류가 발생하였는데, 블록 스코프를 가진 let 변수는 if 문의 중괄호를 벗어나면서 유효성을 상실하였고, 그로 인해 a라는 변수를 찾지못해 오류가 발생하는 것이다.
마치며
현재 대부분의 프로젝트들은 let 과 const를 사용하고 있다. 아닌 프로젝트가 있다면 예전부터 만들어져 수정하기 힘들어진 대형 레거시 프로젝트 정도가 아닐까 싶다.
일반적으로 변수의 스코프는 좁을수록 개발이 용이하기 때문에 let 과 const를 적극적으로 사용하는 것이 안전할 것이다.