상세 컨텐츠

본문 제목

1) 변수선언 키워드의 차이 var, let, const

Basic_Code

by developia_yeso 2023. 12. 13. 14:55

본문

 

 

 

**변수선언이 세 가지가 생긴 이유 ?

 

ES6 버전 이전엔 변수명을 선언하는 키워드 var를 사용했으나 ES6버전 이후엔 사용을 지양하는 편이다

var의 단점을 보완하기 위해 등장한 키워드가 let , const 인데 이 세가지의 특징과 차이점을 알아보자.

 

 

1. var

 

1) 중복선언이 가능하다. 

 

var의 키워드는 중복으로 변수명 선언이 가능하다. 이는 자바스크립트의 무한한 확장의 장점이기도 하지만 의도치않게 변수명 중복을 인지하지 못해 값이 변화하는 결과를 초래하기도한다.

 

중복선언이 가능해 오류발생이 없고 값이 교체된다.

 

 

 

2)값의 재할당이 가능하다. ( let과의 공통점 )

 

값의 재할당으로 자유롭게 값을 변경하기가 편하다. 그러나 의도치 않는 재할당의 경우가 생기기도 한다.

 

 

 

 

 

3)함수레벨스코프를 지향한다. (function-level-scope) / 전역변수, 지역변수

 

var의 가장 큰 특징 중 하나는 함수레벨스코프를 지향하므로 함수외에 코드블록에 선언한 변수명들은 전부 전역변수가 된다.

 

if문안에 변수명을 선언시 지역변수가 아닌 전역변수가 됨을 알 수 있다.

 

함수내에 변수명을 선언시 지역변수로만 작동함을 알 수 있다.

 

 

이러한 var의 특징은 함수내에 선언한 변수명을 제외한 대부분의 변수명을 모두 전역변수로 만들기 때문에 코드관리를 매우 어렵게 만든다. 또한 변수명의 중복이 가능하므로 의도치않게 값이 대체될 우려가 있는 등 애로사항이 많다.

 

 

 

 

4)변수 호이스팅이 있다.

 

var로 선언한 변수명은 기존 값을 undefined로 가지게 된다. 변수 선언한 이후 아직 변수에 값을 할당하지 않았다면 변수 선언에 의해 확보된 메모리 공간은 비어있을 것으로 짐작하나 확보된 메모리 공간에는 자바스크립트 엔진에 의해 undefined라는 값이 암묵적으로 할당되어 초기화된다. 이것은 자바스크립트의 독특한 특징이다.

 

값을 할당하지 않은 채 선언만 했어도 초기값 (undefined)이 발생한다.

 

 

** var tistory (선언) => 선언단계 == 초기화단계 (tistory  == undefinded) >> tistory  = 1; (할당) => 할당단계 (tistory === 1) **

 

알아가자!) 자바스크립트 엔진은 변수 선언을  2단계에 거쳐 수행한다.

 

1. 선언단계 (변수이름을 등록해 자바스크립트 엔진에 변수존재를 알림) 

2. 초기화단계 (값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화)

 

undefined는 자바스크립트에서 제공하는 원시타입의 값이다. 따라서 var의 경우 값을 선언함과 동시에 초기화단계가 함께 진행되어 undefined라는 값을 암묵적으로 할당 받는다. 

이는 변수호이스팅을 발생하는 이유가 되기도 하는데 그 이유는 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임(runtime)이 아니라 그 이전 단계에서 먼저 실행되기 때문이다. 자바스크립트는 소스코드를 순차적으로 실행하기에 앞서 먼저 소스코드의 평가과정을 거치면서 준비를 하는데 이 과정에서 자바스크립트 엔진은 변수 선언을 포함한 모든 선언문(변수 선언문, 함수선언문 등)을 소스코드에서 찾아 먼저 실행한다.

 

선언이 되기도 전에 undefined값을 할당받음

 

그러므로 런타임(순차적실행)에 의한 실행이라면 참조에러가 발생해야하지만 undefined가 출력됨을 알 수 있다. 이는 변수선언이 소스코드가 순차적으로 발생하는 런타임 이전 단계에서 먼저 실행됨을 의미한다. 이처럼 변수 선언문이 선두로 끌어올려져 동작하는 자바스크립트 고유의 특징을 변수 호이스팅(variable hoisting)이라 한다. 

사실 변수 선언 뿐 아니라 var, let, const, function, function*, class 키워드를 사용해서 선언하는 모든 식별자(변수,함수,클래스 등)는 호이스팅이 된다. 

모든 선언문은 런타임 이전 단계에서 먼저 실행되기 때문이다. 그러나 let, const의 경우 var와는 다른 변수의 생명주기를 가지기 때문에 이러한 호이스팅이 발생하지 않도록 할 수 있다. 

 

 

 

2. let 

 

1) 중복선언이 금지 되어 있다.

 

var의 단점을 보완하기 위해 등장한 let은 중복선언이 금지가 되어있다. let 키워드로 이름이 같은 변수를 중복 선언하면 문법에러가 발생한다.

 

 

 

 

2)값의 재할당이 가능하다. ( = const와의 비교점)

 

let의 경우 const 와는 다르게 값의 재할당이 가능하다. 

 

 

 

 

2)블록 레벨 스코프를 지향한다.  / 전역변수, 지역변수

 

let 키워드로 선언한 변수는 모든 코드블록 (함수, if문, for문, while문, try/catch 문 등등) 을 지역스코프로 인정하는 블록레벨스코프(block-level-scope)를 따른다.

 

 

- if문

tistoryText는 if문내에서만 동작하는 지역변수로 선언되었다.

 

 

- function 문

 

 

블록레벨스코프를 지향하기 때문에 전역변수, 지역변수를 구별하기가 용이하며 코드관리가 수월하다. 

 

 

 

 

tistoryContent01값을 지역변수로 선언했을 경우, 함수문을 벗어나면 전역변수로 선언된 tistoryContent01값을 추출한다.

 

 

 

 

 

3) 변수 호이스팅이 없다 ( 없는것처럼 보인다 )

 

var의 변수호이스팅 문제를 보완하기 위한 let 변수 생명주기의 사이클은 차이점이 있다. 

 

** let tistory (선언) => 선언단계 => 일시적 사각지대(TDZ - Temporary Dead Zone) => 초기화단계 (tistory  == undefinded) >> tistory  = 1; (할당) => 할당단계 (tistory === 1) **

 

초기화 단계가 실행되기 이전 변수에 접근하려고하면 참조에러가 발생한다. 이는 선언 == 초기화단계였던 var와는 다르게 변수를 참조할 수 없는 구간 일시적 사각지대를 둠으로써 변수호이스팅이 발생하지 않는 것처럼 보인다.

 

일시적사각지대로 인해 참조에러가 발생하고 선언된 이후에야 undefined 값이 할당된다.

 

 

 

 그러나 변수 호이스팅이 없는 것은 아니고, 없는 것처럼 보일 뿐이다!

앞서 말했듯이 자바스크립트는 ES6에 도입된 let , const를 포함해 모든 선언 (var, let, const, function, function*, class 등) 을 호이스팅하지만 

let,const,class를 사용한 선언문은 호이스팅이 발생하지 않는 것 처럼 작동한다.

 

지역변수를 먼저 소스코드가 인지를 했기 때문에 전역변수의 값을 읽어내지 못했다.

 

변수호이스팅의 발생으로 tistory 전역변수를 읽어내지 못하고 참조에러를 발생시킨다. 이것은 지역변수를 런타임보다 자바스크립트 엔진이 먼저 인지를 했기 때문에 발생하는 오류이다.

 

 

 

4) 전역객체와 let

 

var키워드로 선언한 전역변수와 전역함수, 그리고 선언하지 않은 변수에 값을 할당한 암묵적 전역은 전역객체 window의 프로퍼티가 된다. 전역 객체의 프로퍼티를 참조할 때 window를 생략할 수 있다.

 

그러나 let키워드로 선언한 전역변수는 전역객체의 프로퍼티가 아니다. 즉 window.프로퍼티 같이 접근할 수 없다. 

 

 

- var의 경우

 

이러한 예제는 브라우저 환경에서 실행해야 결과를 확인할 수 있다
브라우저 검사창에서 확인했을 때

 

 

- let의 경우

 

undefined가 뜬다.

 

브라우저창에서 검사했을 때

 

 

 

 

3. const

 

const 키워드이 특징은 let과 대부분 유사하므로 let과의 차이점을 위주로 살펴본다.

 

 

1) 선언과 동시에 초기화 해야한다.

 

const 는 변수명을 선언하는것과 동시에 값을 할당해야한다. 

 

선언만했을 경우 문법에러가 발생한다.

 

선언과 동시에 값을 할당해야 오류가 발생하지 않는다.

 

 

2) 재할당 금지

 

let 과는 다르게 const는 재할당이 금지된다.

 

 

 

3) 상수

 

const 키워드로 선언한 변수에 원시값을 할당한 경우, 변수값을 변경할 수 없다. 원시값은 변경 불가능한 값이므로 재할당 없이 변경할 수 있는 방법이 없기 때문이다. 이 특징을 이용해 const 키워드를 상수를 표현하는데 사용하기도 한다. 이것은 코드의 상태유지, 가독성, 유지보수 편의에 용이하다.

 

 

변경할 수 없는 원시값의 변수명은 대문자로 선언해 상수임을 명확히 나타내며 이후 세후변동이 있을 경우 상수값만을 수정하면 되므로 유지보수에 용이하다.

 

 

 

 

4) 블록레벨스코프를 가지며 변수호이스팅이 발생하지 않는 것처럼 동작한다.

 

변수호이스팅이 발생하나 발생하지 않은 것처럼 보이며 블록레벨스코프를 따르는 것을 알 수 있다.

 

 

5) const 키워드 및 객체

 

const는 값을 재할당하는 것을 금지할 뿐 불변을 의미하지는 않는다. 다시 말해 새로운 값을 재할당하는 것은 불가능하지만 프로퍼티 동적 생성, 삭제, 프로퍼티 값의 변경을 통해 객체를 변경하는 것은 가능하다. 객체가 변경되더라도 변수에 할당된 참조값은 변경되지 않는다.

 

 

객체를 통해 값을 변경

 

 

 

 

관련글 더보기