프로그래밍에서의 변수란 데이터들을 저장하는 공간을 뜻한다. 변수는 값 자체를 뜻하는 것이 아니라 물건들을 저장할 수 있는 작은 상자와 같이, 변경될 수 있는 값을 위한 컨테이너라고 할 수 있다. 자바스크립트에서도 데이터를 담기 위해서 변수를 선언해야 하고, 또한 변수를 선언하기 위해서는 변수 선언자의 사용이 필요하다.
이번 글에서는 javascript에서 사용되는 변수 선언 var, let, const에 대해 알아보고, 각자의 특징과 차이점을 비교해보도록 하자.
자바스크립트에는 왜 변수 선언이 3가지나 되는 것일까?
결론부터 말하자면, var이 먼저 생기고 나서 var의 문제점을 해결하기 위해 const와 let이라는 변수가 나타나게 되었다. ES5까지 변수를 선언할 수 있는 유일한 방법은 var 키워드를 사용하는 것이었다.
먼저 var의 특징을 살펴보면서 ES6부터 let, const가 등장할 수 밖에 없었던 문제점에 대해 알아보자.
var x = 2;
var y = 4;
var z = x + y; // 결과값 6
console.log("z출력값:", z)
var 선언을 사용하여 x,y라는 변수에 값을 지정하고, z라는 변수에 수식을 넣어서 결과값을 도출하는 코드를 생성하였다.
x = 8;
z = x + y; // 12
console.log("z출력값 2:", z);
위의 코드에 이어서 다시 x라는 변수에 새로운 값을 입력시켜도 결과값으로 오류 없이 새 값이 수식에 반영된 결과가 도출이 된다.
이처럼 var는 이미 선언된 변수에 값을 재할당 할 수 있는 특징을 가지고 있다.
var x = 10
var y = 11;
var z = x + y; // 21
console.log("z출력값 3:", z);
또한, 이미 선언된 변수명 x,y와 동일한 이름으로 값을 재선언하여도 문제없이 변수 z의 수식을 거쳐 결과값이 나오게 된다. var는 이미 설정된 변수명으로도 값의 재할당이 가능하다.
하지만 위 방법의 문제점은 한 눈에 알아볼 수 있는 정도의 코드 양이라면 문제가 없겠지만, 코드의 양이 많아 질 경우에 상위에서 이미 선언된 변수명인지 한눈에 확인하지 못하여 하위에서 재선언을 하게 되는 경우같은 의도치 않는 에러를 발생시킬 수 있는 가능성이 크다.
ES6는 이러한 var의 단점을 보완하기 위해 let과 const 키워드를 도입하게 되었다.
let x = 5;
let y = 7;
let z = z + y; // 12
console.log("z출력값:",z);
x = 2;
y = 3;
z = x + y;
console.log("z출력값 2:", z);
var과 마찬가지로 let도 이미 선언된 변수명에 값의 재할당이 가능하다.
let x1 =
하지만, 이처럼 동일한 변수명으로 변수의 재선언을 하려고 한다면 해당 변수가 이미 선언되었다는 에러 메시지가 발생하게 된다. let은 중복 선언이 불가능하다.
constant의 약자인 const는 '상수'라는 의미로,절대 변하지 않는 상수값을 선언할 때 사용한다.
const(상수값) 변수명의 표기법은 보통 대문자를 이용하여 작성한다.
const PI = 3.14;
변하지 않는 파이와 같은 상수값을 선언할 때 const로 선언을 할 수 있다.
PI = 3.16;
하지만, 이처럼 동일한 변수명에 새로운 값을 할당하려고 한다면 에러가 발생하게 된다.
const는 변수를 선언하는 시점에 값을 할당하게 되고 그 값은 바꿀 수 없다.
const는 let과 달리 값을 재할당 할 수 없으며, var과 달리 동일한 변수명으로의 재선언도 불가능하다.
const dateFormat = "YYY-MM-DD";
추가적으로 const를 사용하게 되는 상황의 예를 들자면, 날짜를 표기하여야하는 경우 2022.12.25 또는 2022/12/25, 22-12-25 등 동일한 시스템에서 표시법이 다양할 수가 있다.
이런 경우 사용자는 혼란이 오기 때문에 시스템에서의 표준이 있는 것이 필요하다.
이런 상황에 개발자는 상수값으로 표준이 될 형식을 const를 사용하여 선언을 할 수 있다.
var | let | const | |
---|---|---|---|
재선언 | 가능 | 불가능 | 불가능 |
재할당 | 가능 | 가능 | 불가능 |
스코프란 식별자(변수명, 함수명, 클래스명 등)의 유효범위를 뜻하며, 변수는 선언된 위치에 따라 유효 범위가 달라진다.예를 들어, 함수 내부에서 선언된 변수는 함수 내부에서만 참조가 가능하다. 이 경우 변수의 스코프는 함수 내부로 한정 된다. 전역에 선언된 변수는 전역 스코프를, 지역에 선언된 변수는 지역 스코프를 갖는다. 전역 변수는 어디에서든지 참조가 가능한 값이다. 반면, 지역 변수는 자신의 지역 스코프와 그 하위 지역 스코프에서 유효하다.
function test(){
var a = 4;
console.log(a);
}
test(); // 4
console.log(a); //ReferenceError: a is not defined
var는 함수 내부에 선언된 변수만 지역변수로 한정하며, 나머지는 모두 전역변수로 간주한다.
test 함수 내부에서 선언된 a 변수는 함수 내부에서만 참조 가능하며, 외부에서 참조시 에러 발생!
if(true) {
var a = 5;
console.log(a); // 5
}
console.log(a); // 10
하지만, 함수를 제외한 영역에서 var로 선언한 변수는 전역변수로 취급된다.
if, for, while, try/catch문 등의 코드 블럭 내부에서 var로 선언된 변수는 전역 변수로 간주한다.
let, const는 함수 내부는 물론, if나 for문 등의 코드 블럭에서 선언된 변수도 지역변수로 취급한다.
if(true) {
let a = 4;
console.log(a); // 4
}
console.log(a); // ReferenceError: a is not defined
if문의 블럭 내부에서 let으로 선언된 변수는 외부에서 참조되지 않음을 알 수 있다.
호이스팅이란 자바스크립트가 코드를 실행하기 전, 변수 선언/함수 선언이 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상을 말한다. 물리적인 코드의 상단으로 이동되는 것과 똑같이 동작하지만 변수의 초기화까지 코드 상단에 위치한다는 의미는 아니다.
x; //undefined
var x = 4;
x; //4
t(); //'t'
function t(){
console.log('t');
}
=> var를 선언하기 전에 호출하면 undefined / 선언 후 할당한 결과값 출력됨
: 자바스크립트에서 변수는 선언 단계 - 초기화 단계 - 할당 단계를 거치게 되는데, 이 중 선언 단계만이 코드 상단으로 이동한다. 이러한 이유로 실제 함수나 변수에는 접근할 수 있지만, 변수에 할당한 함수나 변수 자체의 값 대입은 실제 코드 위치에서 일어난다.
x; //ReferrenceError
t(); //ReferrenceError
let x = 44;
let t = function(){
console.log('t');
}
하지만 위와 같은 로직에 let으로 변수를 선언하게 되면, ReferenceError가 발생하고 그 변수는 선언하기 전에는 존재하지 않는 상태로 출력된다. 반대로 var로 선언한 변수는 현재의 스코프에서는 어디서든 사용할 수 있으며, 심지어 선언 전에도 사용할 수 있다.
var | let | const | |
---|---|---|---|
사용 권장 | 3순위 | 2순위 | 1순위 |
재선언 | 가능 | 불가능 | 불가능 |
재할당 | 가능 | 가능 | 불가능 |
hoisting | 가능 | 불가능 | 불가능 |
scope | 함수 스코프 | 블록 스코프 | 블록 스코프 |
기본적으로 변수의 스코프는 최대한 좁게 만드는 것을 권장한다고 한다. 정리하자면, const와 let을 이용해서 변수를 선언하고 값을 재할당하는 경우가 아니라면 const를 최우선적으로 사용하는 것이 좋은 것 같다. 그리고 var는 정말 특별한 경우가 아니라면 사용하지 않는 편이 좋다고 보인다.
변수 선언에도 하나가 아닌 다양한 선언문이 존재한다는것이 학습전에는 복잡해보였지만, ES의 흐름에 따라 변화된 기능의 특징들을 알아보면서 결국 더 편리하고 사용성 있는 코드의 품질과 프로그래밍 환경을 만들어가기 위한 변화의 발자국이라는 사실을 깨닫게 되어 흥미로웠다.
📚 참고한 사이트들
https://developer.mozilla.org/ko/docs/Learn/JavaScript/First_steps/Variables
https://developer.mozilla.org/ko/docs/Glossary/Hoisting
https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html
https://youtu.be/8M_8zGB7phs
https://youtu.be/IGnq35c6nP4