JavaScript 변수 var에 대하여
문제점 😅
스크립트에 관해 구글링 하다보면 변수 선언 시 var
가 아닌 let
으로 시작하는 글을 종종 봤다. 내가 경험한 프로젝트 코드에서도 var
를 사용하고 있고 나또한 아직도 var
를 사용해왔는데, 모던 JavaScript 튜토리얼를 읽어보고 최신 스타일에 맞춰서 코딩하는 습관이 필요할 것 같아서 정리해둔다.
해결책 😏
사실상 var
와 let
의 큰 차이는 없지만 var
의 특이점은 알아둬야겠다.
var는 블록 스코프가 없다.
아주 오래전의 자바스크립트에선 블록 수준 렉시컬 환경이 만들어 지지 않았다고 한다. 그래서 var
로 선언한 변수는 블록이나 루프 수준으로는 스코프1가 생기지 않기 때문에 블록 밖에서 접근 가능하다.
// test 1: if문 블록
if (true) {
var msg1 = 'welcome!'; // 'let' 대신 'var'를 사용.
}
console.log(msg1); // welcome! (if 문이 끝났어도 변수에 여전히 접근할 수 있음)
if (false) {
var msg2 = 'devlog!'; // 'let' 대신 'var'를 사용.
}
console.log(msg2); // undefined
// test 2: for문 블록
for (var num = 0; num < 10; num++) {
console.log("My number is "+num); // My number is 0 ~ 9까지 log 출력.
}
alert(num); // 10, 반복문이 종료되었지만 'num'은 전역 변수이므로 여전히 접근 가능.
var
는 if
, for
등의 코드 블록을 관통한다. 그렇다면 var
는 항상 전역 변수로만 사용되는 걸까?
// test 3: 함수 단위 블록
function echo() {
if (true) {
var say = "yaaaaaaahooooo!!!!";
}
alert(say); // 제대로 출력
}
echo();
alert(say); // Uncaught ReferenceError: say is not defined
var
로 선언된 변수는 if
블록 안에 있지만 블록 수준의 스코프가 생기지 않으므로 echo()
안에서의 alert()
은 정상적으로 작동한다. 하지만 함수 블록을 벗어난 곳에서 호출 시 에러가 발생한다. 즉, 코드 블록이 함수 안에 있다면, var
는 함수 레벨 변수가 된다.
let은 블록 스코프가 있다.
상기 코드를 let
으로 바꿔보자.
// test 1: if문 블록
if (true) {
let msg1 = 'welcome!'; // 'let'으로 변수를 선언함
}
console.log(msg1); // Uncaught ReferenceError: msg1 is not defined
if (false) {
let msg2 = 'devlog!'; // 'let'으로 변수를 선언함
}
console.log(msg2); // Uncaught ReferenceError: msg2 is not defined
// test 2: for문 블록
for (let num = 0; num < 10; num++) {
console.log("My number is "+num); // My number is 0 ~ 9까지 log 출력.
}
alert(num); // Uncaught ReferenceError: num is not defined
// test 3: 함수 단위 블록
function echo() {
if (true) {
let say = "yaaaaaaahooooo!!!!";
}
alert(say); // Uncaught ReferenceError: say is not defined
}
echo();
alert(say);
블록수준의 스코프가 생겼으므로, 좀 더 안전하게(우리가 일반적으로 알고 있는 절차로) 로직 작성을 할 수 있다.
var는 변수의 중복 선언을 허용한다.
var
로 같은 변수를 여러번 중복으로 선언할 수 있다.
var user = "Pete";
var user = "John"; // 이 "var"는 아무것도 하지 않는다(이전에 이미 선언됨).
// ...에러 또한 발생하지 않는다.
alert(user); // John
그러나 동일한 코드를 let
으로 바꾸면, 같은 변수를 let
으로 두 번 선언했기 때문에 에러가 발생한다.
let user;
let user; // Uncaught SyntaxError: Identifier 'user' has already been declared
선언하기 전 사용할 수 있는 var 그리고 호이스팅(hoisting)
var
선언은 함수가 시작될 때 처리된다. 아래의 코드를 실행시키면 놀랍게도 실행이 잘된다.
function echo() {
say = "yaaaaaaahooooo!!!!";
if (false) {
var say;
}
alert(say);
}
echo(); // yaaaaaaahooooo!!!!
var
로 선언한 모든 변수는 함수의 최상위로 끌어 올려지는데, 이를 호이스팅(hoisting) 이라고 한다.
if(false)
블록 안 코드는 절대 실행되지 않지만, 호이스팅에 전혀 영향주지 않는다.- 호이스팅으로 인해 변수 선언은 선언 위치 상관없이 함수가 시작되는 지점에서 정의된다.
- 변수 선언(var)은 호이스팅이 되지만, 변수 할당(=)은 호이스팅이 되지 않는다.
따라서 위의 코드는 아래 순서처럼 해석할 수 있다.
function echo() {
var say;
say = "yaaaaaaahooooo!!!!";
alert(say);
}
echo(); // yaaaaaaahooooo!!!!
마무리 😎
var
와 let
의 중요한 차이점을 알아보았다. var
는 예기치 못한 프로세스상의 로직 오류를 일으킬 수 있으므로, 앞으로는 let
을 사용하는 습관을 들이자. 좀 더 상세한 내용은 아래의 참고문헌 링크 참조!
참고문헌 📝
https://ko.javascript.info/var
https://ko.javascript.info/variables
-
스코프(Scope): 변수에 접근할 수 있는 범위, 전역(Global)과 지역(Local) 2가지 유형이 있다. ↩