var는 ES5 시절까지는 변수를 선언할 수 있는 유일한 키워드였으나,  몇 가지의 치명적인 단점이 있기에 ES6에서는 그 단점을 보완할 변수 키워드 let, const를 만들게 되었습니다. 앞서서 var 키워드가 어떤점이 문제 였는지 확인해보겠습다.

var의 문제점

1. 변수 중복 선언 허용 

var, let을 이용한 중복 선언 출력값

위 코드에서 볼 수 있듯이 var 키워드는 재할당도 아닌 재 선언을 저렇게 허용을 하고, let 먼저 저렇게 이미 선언됬다고 친절히 말해주는 것을 알 수 있습니다. 사용자가 동일한 이름의 변수가 이미 선언됬는지 모르고 그냥 선언하면서 할당 값도 바꾸게되면 부작용이 발생할 수 있습니다.

 

 

2. 함수 레벨 스코프 

var, let 이용한 스코프에서의 변수생명주기

위 코드에서 볼 수 있듯이 문제는 명확하다. 일단 스코프에는 간단히 함수 스코프와 블록 스코프로 나눌수 있는데, 

함수 스코프 : 함수안에서 수행할 명령문들을 중괄호로 감싼 유효 범위{ }라고 할 수 있고,

블록 스코프 : if, for, while문에서 유효 범위를 나타낸 { } 게 블록 스코프라고 할 수 있다. 

쉽게 말하면 var 는 선택적 분노장애다. 블록 스코프에서 선언되면 해당 문이 끝나더라도 같이 사라지지 않고 전역변수의 형태로 계속 살아남아 있다. 하지만 함수 스코프에서는 함수가 종료하자마자 같이  자신의 생명주기를 끝내버린다. 그에 반해 let 은 평등하게 문이 끝나면 뒤끝없이 깔끔하게 사라져 주니 얼마나 좋은가.. 

 

 

3. 변수 호이스팅

자바스크립트의 특징중에 하나인 호이스팅이다. 일단 간단한 호이스팅을 두 키워드로 비교해보자.



var로 변수를 선언하면 왼쪽에 주석으로 출력을 값을 적어놓은 것처럼 나오는데, 순서대로 짚어보자면 

1. 변수 hoist가 호이스팅되면서, 이때 선언 단계, 초기화 단계를 동시에 수행하며 식별자의 존재를 알리게되고, undefined      로 초기화.

2. 1번 라인 console.log 에서 undefined가 출력됨

3. 3번 라인 console.log 에서 undefined가 출력됨 아직까지 변수에 할당값이 없기 때문이죠.

4. hoist 변수에 값을 할당합니다. 여기서 할당 단계 실행

5. 5번 라인 console.log 에서 할당된 값 1을 출력하게 됩니다.

 

let으로 변수를 선언하면 오른쪽처럼 출력이 나오는데, 이것또한 순서대로 짚어보겠습니다. 

1. 변수 hoist가 호이스팅되면서, 이때 선언 단계만 ! 실행이되면서 식별자의 존재를 알리게됩니다. 하지만 초기화 X

2. 1번 라인 console.log 에서 참조에러가 발생합니다. 변수의 존재는 알지만 초기화 단계가

     아직 실행되지 않았기 때문이죠. 그래서 스코프의 시작 지점과 초기화단계가 실행될 수 있는 변수 선언문까지

    참조할 수 없습니다. 이 구간을 일시적 사각지대 (TDZ)라고 부릅니다.

    그래서 코드는 원래 여기서 에러나서 끝나야하지만 굳이 다음으로 넘어가보겠습니다.

3. 3번 라인 console.log 에서 undefined를 출력합니다. 2번 라인에서 초기화 단계가 실행되어 참조가 가능합니다.

4. hoist 변수에 값을 할당합니다. 여기서 할당 단계 실행

5. 5번 라인 console.log 에서 할당된 값 1을 출력하게 됩니다.

 

 

여기서 포인트는 let 키워드로 선언한 변수는 "선언단계"와 "초기화 단계"가 분리되어 진행된다는 것을 기억하면 될 것 같습니다. 호이스팅이 안되는 것처럼보이지만 단순히 초기화단계가 이루어지지 않아 참조를 못할 뿐입니다. 

 

 

4. 전역 객체와 let 

var x = 1; // 전역 변수
let y = 2; // 전역 변수
z = 3; // 암묵적 전역


function foo() {} // 전역 함수 

// var 선언한 전역 변수는 전역 객체 window의 프로퍼티다.
console.log(window.x); // 1
console.log(window.y); // undefined
// Uncaught SyntaxError: 'y' has already been

// window의 프로퍼티는 전역 변수처럼 사용할 수 있다.
console.log(x); // 1
console.log(y); // 2

// 암묵적 전역은 전역 객체 window의 프로퍼티다.
console.log(window.z); // 3
console.log(z); // 3

// 전역 함수는 전역 객체 window의 프로퍼티다.
console.log(window.foo); // ƒ foo() {}
// window의 프로퍼티는 전역 변수처럼 사용할 수 있다.
console.log(foo); // ƒ foo() {}

 

전역 객체인 window 의 프로퍼티가 되는 경우가 몇가지 있습니다. 위에 코드를 보면 아실 수 있겠지만 

1. var 키워드를 이용한 전역 변수 선언

2. 키워드를 넣지않는 암묵적 전역 변수 선언

3. 전역 함수 

이렇게 3가지는 window의 프로퍼티가 되는데요, 출력할때, 생략할 수 있어서 저희가 몰랐지만 window를 찍어서 출력을 해보면 바로 알 수 있습니다. 하지만 let은 똑같은 변수를 선언하는 키워드지만 전역 객체의 프로퍼티가 되질 않습니다. 그냥 보이지않는 개념적인 블록내에 존재하게 됩니다. 

 


const 키워드의 특징 

앞서 var와 let을 비교를 하며 차이점을 확인해보았습니다. let의 특징은 const도 가지고 있기에 여기서는 상수를 다루는 const의 특징을 적어보겠습니다. 

 

1. 선언과 초기화 

const test = 1;
const test2 ;
// SyntaxError: Missing initializer in const declaration

상수는 말 그대로 수식이 변하지 않는 값이이므로, 선언과 동시에 할당값을 넣어주지 않는다면 에러가 발생합니다. 

 

2. 재할당 금지 

const test = 1;
test = 2;
// TypeError: Assignment to constant variable.

당연한 거지만 const로 선언된 상수는 재할당이 불가합니다.

 

3. const 키워드와 객체

const myInfo = {
  name:  "evan",
  age: 26,
};
myInfo.name = "chaliie"
console.log(myInfo.name); // challie

const 키워드로 선언된 변수에 객체를 할당한 경우 값을 변경할 수 있습니다. const는 재할당을 불가하지만 불변을 의미하지는 않기 때문입니다.  즉 객체는 변경이 가능합니다.