oris9

[Javascript] var, let, const 열심히 비교해보기 본문

JavaScript

[Javascript] var, let, const 열심히 비교해보기

oris9 2024. 3. 30. 20:34

 

세가지 모두 변수를 선언하는 키워드이다.

`var`는 초기부터 사용된 변수 선언 키워드이고,
`let`과 `const`는 ES6이후 도입되었다.

즉 var의 어떤 문제점에 개선 필요성을 느끼고 추가된 변수 선언 키워드인 것이다 🤨

 

키워드 var

var의 어떤 특징이 문제였을까?

 첫번째로  `var`는 재선언, 재할당이 가능하다.

 언제 같은 이름으로 다시 선언하든, 다른 값을 새롭게 할당하든 계속해서 오류 없이 동작한다.

이 말은, 코드가 복잡해졌을 때 위에서 쓴 변수이름을 앗! 깜박하고 다시 쓰더라도 자바스크립트는 아무런 이상을 느끼지 못하고 코드를 계속 실행한다는 뜻이다.

이렇게 되면 나, 또는 남이 코드를 수정하기 너무 쉬워진다.
변수는 최대한 밖에서 건드리지 못하는 것이 좋은데 밖에서 건드리기 너무 쉬워지는 것이다.

누구나 어디서든, 몇번이든 다시 같은 변수에 값을 넣고 선언하고,, 할 수 있다

 

두번째로 `var`는 함수레벨 스코프를 가진다.

스코프는 그 변수가 사용될 수 있는 유효한 범위를 의미한다.

그런데 함수레벨 스코프를 가지게되면, 말 그대로 함수 내부에서만 지역변수로 동작하게되는 것이다.

`if문` `for문` `while문` 등의 함수가 아닌 `블록단위`에서는 전역변수로 동작하게된다.

특정 블록, 함수 내부의 요소들은 그 단위 안에서 관리되는 것이 코드의 관리면에서 좋고 전역공간을 더럽히지 않기때문에 깨끗한 코드이다.

그런 의미에서 함수레벨 스코프를 가진다는 것은 단점으로 작용할 수 있다 😡

 

세번째로, `var`는 호이스팅 관점에서 `let` `const`와 다르게 동작한다. 

이 말은, 변수가 선언되었을때 일어나는 동작이 `var`와 `let` `const`이 다르다는 것이다.

처음 자바스크립트를 접하고 가장 처음 배우게 되는 let const를 접하고,
기존에 쓰던 var와는 뭐가 달라서 let const만을 사용하라는거지? 

궁금증이 생겨서 찾아보다보면 `스코프` `호이스팅` 에 부딪히게 된다 (ㅠㅠ)

둘을 이해하려면 자바스크립트의 `동작원리`를 이해하는게 큰 도움이 된다

 

간단하게 설명하면,
자바스크립트는 코드 전체를 컴파일(컴퓨터가 이해할 수 있게 번역)하고 실행되는 언어가 아니라
한 줄 씩 코드를 읽어나가면서 코드를 실행하는 인터프리터 언어이다.

그런데 여기서 호이스팅의 개념이 등장하는데,
우선 호이스팅이란 `끌어올리다`는 뜻으로 변수가 선언되면 코드의 맨~ ~윗줄로 선언이 끌려올라간다는 개념이다

처음에 나는 자바스크립트는 인터프리터언어인데 어떻게 호이스팅이 발생하지? 라는 의문이 있었는데
(한줄씩읽으면서 실행되는데, 어떻게 실행시 모든 변수들이 호이스팅이 가능한지)

변수가 담길 메모리 공간이 필요하기 때문에 이를 미리 할당해놓기 위해 실행전에 선언문들을 미리 찾아 내고,
호이스팅이 발생하게 된다고 한다.

(그러므로 끌어올려진다는 호이스팅은 말그대로 실제로 끌어올려진다기보다 이해하기 위한 개념이다.)

 

어떤 변수가 선언되면   

그 변수는 코드의 맨 위쪽으로 `호이스팅` 되어 특정 변수가 선언되었음을 인지한다            ①선언단계
(변수를 실행컨텍스트의 변수객체에 등록 - 이 변수 객체는 스코프가 참조하는대상이 됨)

변수의 초기화가 일어나면서, 값이 undefind가 된다    ②초기화 단계
(변수 객체에 등록된 변수를 위한 공간을 메모리에 확보) 

까지가 기본적인 호이스팅 과정이다. (회색배경색글자가 이해되지 않으면 추가적으로 Execution Context를 공부하면된다)

 

`var`는 끌어올려져서 선언과 초기화가 동시에 일어나기 때문에,
변수 선언시 값을 할당해줬어도          //  (`var name` 처럼 선언만 한게 아니라, `var name = 'min'`과 같이 할당까지 진행해줬어도)
값이 undefind로 초기화 된 상태로 존재하고,
그 변수에 값이 할당되는 코드 줄에 도달되어서 그 줄이 실행될 때, 특정 값이 할당되게 된다



대략적으로라도 호이스팅 과정이 이해되었으면,

계속해서  `var`와 `let` `const`의 호이스팅 과정이 다르고, `var`의 호이스팅과정은 무엇이 문제인지 알아보자

결론적으로 `var`는 내가 선언한 코드 이전에 그 변수를 참조해도 에러가 나지 않는다는 점이 문제이다.
심지어 선언 전에 할당까지 가능하다 

//선언한 코드 이전에 그 변수를 참조해도 에러가 나지 않고 undefind를 반환

console.log(name)      // undefind

var name = "min"
// 선언하기 전에 할당해도 제대로 동작하는 모습..........

name = "max"

console.log(name)      // "max"

var name = "min"

 

선언 전에 할당을 막을 수도 없고, 
할당을 하지 않는다고 하더라도 선언문 실행이전에 변수를 참조해도 undefind만이 반환되기때문에,
코드를 예측하기 어려워지고 디버깅을 어렵게 만든다

 

 

키워드 let , const

let과 const는 위에서 이야기한 var의 단점들을 모두 개선했다

첫번째, let과 const는 재선언이 불가능하다

let과 const를 이용해서 선언한 변수를 다시 한 번 같은 이름의 변수를 만드려고하면 에러를 발생시킨다

`let`은 재할당 가능한 변수 선언 키워드,

`const`는 재할당이 불가능한 변수 선언 키워드로 안에 담기는 값의 타입과 상황을 고려해 맞춰 사용할 수 있다.

재할당이 불가능하게 만들고 싶다면 const로 막아주면 된다. 

const에 재할당을 하게 되면 역시 에러를 던진다.

 

 

두번째, let과 const는 블록레벨 스코프를 가진다

블록레벨 스코프를 가지기 때문에 다루기가 더 편하다

(모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등))

 

 

세번째, let과 const는 호이스팅시 초기화가 일어나지 않는다
어떤 변수가 선언되면   
그 변수는 코드의 맨 위쪽으로 `호이스팅` 되어 특정 변수가 선언되었음을 인지한다  ①선언단계
변수의 초기화가 일어나면서, 값이 undefind가 된다  초기화단계

위에서 설명했던 호이스팅 과정 중 값이 undefind로 초기화되는 과정이 발생하지 않는다.

let, const로 선언된 변수는 호이스팅 시 `Temporal Dead Zone(TDZ, 일시적 사각지대)` 라는 구역에 들어가게되고 

이 구역에 의해 가려지게(접근할수없게) 된다.

실제로 변수가 선언될때 TDZ를 빠져나오게 되며 이때 변수 선언과 초기화가 일어나게된다

(선언문 전까지를 그 변수의 TDZ라고 생각하면 된다)

변수가 초기화가 되지않기 때문에, 변수 선언문이 실행되지 않았을 때 변수를 사용하면 에러를 발생시킨다.   // ReferenceError

 

 

 

 

 

참고 👍

https://medium.com/korbit-engineering/let%EA%B3%BC-const%EB%8A%94-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EB%90%A0%EA%B9%8C-72fcf2fac365