var, let, const를 구분해보자.

var 와 let, const를 구분하고 어떨 때 사용하면 좋을지 알아보자!

Javascript에서 변수 선언 방식인 let,var,const은
function-scopedblock-scoped어느 스코프를 사용하냐로 나뉘어진다.

var의 특징

var
var는 함수(function) 안에서의 변수가 *hoisting된다.
var는 변수 재선언 / 재할당 가능하다.
function안에서의 var를 사용한 변수 선언은 함수 안(scope)에서만 사용가능하지만, 함수가 아닌 다른 scope에서의 var변수 선언은 전역으로 hoisting이 되기 때문에 다른 곳에서 에러가 나지 않고 실행이 된다.
선언과 초기화가 동시에 진행

function-scoped를 사용하는 var


1)
if(true){
	console.log(a);	//undefined  --ReferenceError
	var a = 1;
}
console.log(a);		//1

-------------------------------------------------
  
2) !!hoisting!!
var a = 1;
if(true){
	console.log(a);	//undefined  
}
console.log(a);		//1

1)위처럼 var는 함수 전역으로 hoisting 되기 때문에 if문의 끝났음에도 불구하고 외부에서 a값을 호출 했을 때, a의 값이 출력된다.
2)은 1)과 같다. hoisting이 되기 때문에 제일 위로 끌어올려져서 1)동작이 가능해졌던 것이다.

var는 ReferenceError라는 에러가 나도 실행이 멈추지 않는다라는 단점이 있어, 에러 발생시 에러 발생 지점을 찾기가 어렵다.


let과 const의 특징

  • let과 const는 생략이 불가능하다. 생략 시 var로 간주된다.
  • block-scoped를 사용한다.
  • 선언과 초기화가 분리되어 진행된다.

let
let은 변수에 재할당이 가능하다.

1)
let a;
a = '123';	// let은 선언하고 나중에 값을 할당이 가능.

2)
let name = 'hello';
let name = 'hi';	//Uncaught SyntaxError,재선언 불가

const

  • const는 변수 재선언, 재할당 모두 불가능하다.
  • 선언과 동시에 초기화해야 한다.
  • const는 상수를 선언하기 위해 사용한다.
  • 상수는 재할당이 금지된 변수이기 때문에 값을 변경할 수 없다.
  • 하지만 변수에 객체를 할당했을 경우엔 값을 변경할 수 있다.
1)
const a;	// Missing initializer in const declaration
		// const는 선언과 동시에 값을 할당해야한다.

2)
const name = 'code';
const name = 'we';	//Uncaught SyntaxError

let,const의 hoisting


변수 선언 키워드인 var, let, const 중 어떤 키워드를 사용해도 hoisting은 항상 이루어진다. 똑같이 hoisting이 이루어지고 같은 변수를 선언하는 키워드라도 키워드 마다의 차이는 존재한다.

차이점은 변수를 선언할 때,( v8(내부 엔진)이 변수 객체를 생성할때,) 전부 동일하게 처리하지만 변수를 위해 할당된 메모리 공간을 확보하는 초기화 단계에서 다르게 처리한다.

v8엔진 내부에서 var를 사용한 변수는 kCreatedInitialized를,
let,const를 사용한 변수는 kNeedsInitialization 키워드를 반환한다.

즉, let,const를 사용한 변수의 값은 특별한 이유로 "초기화가 필요한 상태"로 관리되고 있다는 것이다.

초기화가 필요한 상태란?
메모리에 할당된 공간이 할당되지 않았기 때문에 초기화를 하여,
공간을 만들어야하는 상태 = TDZ


  • 변수가 만들어지는 단계

    1) 선언Declaration : 스코프와 변수 객체가 생성되고 스코프가 변수 객체를 참조,
    스코프에 변수를 선언한다.

    2) 초기화Initialization : 변수 객체가 가질 값을 위해 메모리에 공간 할당.
    변수의 값을 초기화 값(undefinded)으로 초기화하며 실제로 변수에 접근 가능한 단계

    3) 할당Assignment : 변수 객체에 값을 할당.
    할당문을 만나면 변수에 실제 값을 할당한다.


변수(객체)를 위한 공간(메모리)을 할당하는 모습

var의 초기화 모습

  • var는 선언과 초기화가 동시에 이루어진다. 선언이 되자마자 undefinded로 값이 초기화.
    var로 선언했을 때,AllocateTo라는 메소드를 사용하여 메모리에 공간을 할당하는 모습

let, const의 초기화 모습

  • let, const는 선언과 초기화가 분리되어 실행.
    선언 단계는 최상단으로 hoisting 되지만, 초기화 단계는 선언문을 만나야 실행.
    그렇기 때문에 let과 const는 선언과 초기화를 동시에 해줘야 에러가 나지 않는다.
    let과 const는 AllocateTo메소드가 호출되지 않고 position값만 정해주는 모습.(let과 const를 사용해 선언된 변수들이 TDZ존에 들어갔다.) == 공간이 할당되지 않았다.

    이때, TDZ존에 들어간 변수 객체에 접근을 시도하면 Cannot access '%' before initialization라는 에러 메세지를 보게 된다.
    선언 단계가 실행되는 스코프 최상단부터 초기화 단계를 실행하는 선언문이 나오기 전까지 변수에 접근할 수 없다.

TDZ(Temporal Dead Zone): 선언은 되어있지만 초기화가 되지않아 변수에 담길 값을 위한 공간이 메모리에 할당이 되지 않은 상태


변수 선언 키워드 간의 차이점

- var는 함수 레벨 스코프를 사용하며, 변수를 생성할 때, 선언과 초기화가 동시에 일어나고 변수의 값을 위한 메모리 공간이 할당되어 에러가 나지 않는다.

- let과 const는 블록 레벨 스코프를 사용하며, 선언과 초기화가 분리되어 일어난다. 선언 후 초기화가 되지 않으면, TDZ에 들어가게 되고 초기화되지않은 변수에 접근하면 TDZ에 들어가 있기 때문에 변수 객체 참조를 방어하여, 오류가 발생한다.

따라서 let과 const를 사용할 때는 선언과 초기화를 동시에 진행해야 오류가 나지 않는다.


const > let > var

var 보단 let, let 보단 const를 활용하자.

  • var는 에러가 나도 찾기 힘들다. 에러가 잘 나지 않는다..
  • let은 변수에 값을 재할당 해야하는 경우가 많지 않다.
  • const는 값을 재할당하려는 경우 에러가 발생하기 때문에 의도치 않게 변수의 값이 재할당되는 상황을 방지할 수 있다.

단어풀이

  • hoisting : (함수를 실행하기 전에 필요한 변수들을 유효 범위의 최상단으로 끌어 올리는 것을 말한다.)
  • function-scoped : 함수 몸체 안에서만 지역 변수로 사용되고, 그 외에 코드블럭{}에서는 전역 변수로 동작한다.
  • block-scoped : 코드 블럭 안에서 변수로 동작

좋은 웹페이지 즐겨찾기