변수와 상수의 이해 var, let, const

자바스크립트에서 변수, 또는 상수를 선언하는 방법은 3가지입니다.

ES5까지 사용하던 구 변수 선언 방식인 var, 그리고 ES6에서 새롭게 추가된 let과 const 가 있습니다.

ES5까지 자바스크립트에는 상수 선언이 없었습니다.

ES6에 와서 const 라는 상수 선언자가 새롭게 생겼습니다.

상수는 모두가 아는데로 초기화 후에는 값을 변경할 수 없습니다.

변수를 선언하는 방법은 var 와 let 이 있습니다

변수 선언자가 2개가 되면서 개념을 이해하지 못해 로직

변수의 스코프

var 와 let은 유사하지만, ES6에서 스코프 개념이 사용되면서 중요한 차이점이 생겼습니다.

var는 변수가 사용되는 범위가 전역, 또는 함수 내부 로컬 2가지만 존재합니다.

let은 변수가 사용되는 범위가 전역, 함수 내부 로컬 외에 코드 블록, 구문, 표현식 로컬로도 정의해 사용할 수 있습니다.

let은 변수가 사용되는 스코프가 존재하기 때문에 변수의 선언 및 활용성이 굉장히 높아집니다.

let으로 선언한 로컬 변수는 선언된 블록의 하위 블록, 구문, 표현식에서 접근 가능합니다.

자바스크립트 코딩을 할 때 var, 또는 let 둘 중 하나만 사용하는 것이 좋습니다.

당연하지만 스코프 개념을 지원해 변수 사용상의 오류를 줄일 수 있는 새로운 let을 권장합니다.

전역 객체의 속성

그리고 var와 let은  전역객체 this 속성으로 접근하는 방법에도 차이가 있습니다.

var 로 생성한 변수는 전역 객체 속성이 생성되어 전역 객체로 접근할 수 있습니다.

let 은 더이상 전역객체 속성이 생성되지 않습니다. 

전역 변수로 선언했으므로 전역으로 접근이 가능하지만, 전역 객체 속성으로는 접근이 불가능합니다.

var str1 = 'var';let str2 = 'let';
console.log(this.str1);console.log(this.str2);
function run(){  console.log(this.str1);  console.log(this.str2);  console.log(str1);  console.log(str2);}run();

변수 호이스팅(Hoisting)

var 로 함수 중간에 선언된 변수들은 호이스팅이라는 자바스크립트의 특징으로 인해 런타임 시점에 함수 맨 위로 이동합니다.

스크립팅 언어인 자바스크립트가 선언 없이 변수를 사용되면서 발생하는 사각지대로 인한 에러를 방지하기 위한 기법입니다.

선언하기 전에 사용한 변수는 호이스팅에 의해 위로 끌어 올려져 선언은 되어있지만, 초기화가 되지 않았기 때문에 Undefined 상태인 변수가 됩니다.

반면 let은 호이스팅을 하지 않습니다.

변수가 선언되기 전에 사용되면 에러("error")가 발생합니다.

console.log(str1);console.log(str2);
var str1 = 'var';let str2 = 'let';

변수 호이스팅이 편리하기는 하지만, 자바스크립트 코드가 길 경우 변수 호이스팅으로 인한 오버헤드가 발생하는 단점이 있습니다.

let 으로 변수를 선언해 사용할 경우에는 반드시 변수 선언 후에 사용해야 합니다.

var 와 let 이 서로 장단점이 있지만, 이런 개념상의 차이로 인해 var 또는 let 한가지만 사용해서 코딩하는 것을 권장합니다.

조금 극단적이지만 아래와 같이 var와 let을 함께 사용하는 경우, 에러가 발생하고, 개념을 혼동하면 에러의 원인을 찾는데 애를 먹게 됩니다.

function run(){    var sum = 0;    if(true){        let sum = sum + 10;    }}run();

let은 스코프 개념을 사용하므로 if 블록 안의 let sum은 if 블록 바깥의 var sum 과는 다른 로컬 변수입니다.

그리고, sum + 10 의 sum 은 var sum 의 sum 이 아니라 let sum의 sum 이 됩니다.

let sum은 아직 초기화가 되지 않았기 때문에 sum + 10 의 sum은 에러가 발생합니다.

이 오류는 let의 개념이 명확하지 않은 상태에서 사용하기 때문에 발생합니다.

같은 변수명으로 스코프를 지원하는 let sum 을 하위 코드 블록이나 구문에 선언해 사용하는 경우 반드시 선언 후에 사용해야 합니다.

let sum = sum + 10;

이 계산식은 다음의 순서로 해석됩니다.

1. let sum 으로 변수 선언이 됩니다.

2. let sum 에 초기화 값을 대입해야 하는데 오른쪽 리터럴이 계산식이므로 초기화 전에 계산식 계산이 먼저 실행됩니다. 

   이때 let sum은 선언만 되고 초기화가 안된게 중요합니다.

3. 계산식 sum + 10 을 실행하는데 sum 이 선언만 되어 있습니다. 따라서 오류가 발생합니다.

   let 으로 선언한 변수는 초기화 전에 사용하면 에러가 발생합니다.

   여기서 sum을 상위에 선언된 var sum을 가져온다고 착각하면 안됩니다. 

   if 블록 안에 이미 let sum이 선언되어 있기 때문에 스코핑 원칙에 따라 내부의 sum을 가져다 쓰려고 시도합니다.

위 코드는 

let sum = 0;sum = sum + 10;

이렇게 선언과 초기화를 먼저한 후 사용하면 해결됩니다.

만약 상위에 선언한 var sum을 사용하려는 것이 목적이라면 let sum의 let을 소거하거나 변수명을 다르게 해야 합니다.