> For the complete documentation index, see [llms.txt](https://wlgus3.gitbook.io/jhs-modern-js-deep-dive-note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wlgus3.gitbook.io/jhs-modern-js-deep-dive-note/04.md).

# 04 변수

## 4.1 변수란 무엇인가? 왜 필요한가?

애플리케이션은 아무리 복잡하다고 해도 데이터를 입력받아 처리하고 그 결과를 출력하는 것이 전부다. 변수는 프로그래밍 언어에서 데이터를 관리하기 위한 핵심 개념이다.

```javascript
10 + 20
```

자바스크립트 엔진이 위 자바스크립트 코드를 계산하려면 먼저 10,20,+ 라는 기호( 리터럴과 연산자)의 의미를 알고 있어야 하며 , 10+ 20 이라는 식(표현식)의 의미도 해석( 파싱 parsing ) 할 수 있어야 한다. 컴퓨터는 CPU를 사용해서 연산하고, 메모리를 사용해 데이터를 기억한다.

메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체며, 메모리 셀은 1바이트 (8비트)이고 컴퓨터는 메모리 셀의 크기인 1바이트 단위로 데이터를 저장하거나 읽어 들인다.

각 셀은 고유의 메모리 주소를 갖는다. 0\~ 메모리 크기만큼 정수로 표현한다.

메모리 주소의 할당은 동일한 컴퓨터로 동일한 코드를 실행하더라도 상황에 따라 매번 달라진다. 따라서 메모리 주소 자체로 데이터를 제어하는 것은 **매우 위험하며 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.**&#x20;

따라서 기억하고 싶은 값을 메모리에 저장하고, 그 값을 읽어들여 재사용하기 위해서 변수라는 메커니즘을 제공한다.&#x20;

**\[변수]는&#x20;**<mark style="color:purple;">**하나의 값을 저장하기 위해 확보한 메모리 공간 자체**</mark>**&#x20;또는&#x20;**<mark style="color:purple;">**그 메모리 공간을 식별하기 위해 붙인 이름**</mark>**을 뜻한다.** 즉 변수는 **값의 위치를 가리키는 상징적인 이름**이다.

* **\[할당]** **assignment** 대입, 저장 -<mark style="color:purple;">변수에 값을 저장</mark>하는 것
* **\[참조] reference** - 변수에 저장된 값을 읽어 들이는 것 : 변수나 데이터 구조 등이 <mark style="color:purple;">메모리 상의 위치를 가리키는 것</mark>을 의미

## 4.2 식별자

**변수 이름**을 **\[식별자] idetifier**라고도 한다.

&#x20;식별자는 **어떤 값을 구별해서 식별할 수 있는 고유한 이름**을 말한다. 식별자는 값이 아니라 **메모리 주소를 기억**하고 있다. 즉, **식별자는 메모리 주소에 붙인 이름**이라고 할 수 있다.&#x20;

식별자는 변수 이름 뿐만 아니라 **함수, 클래스 등의 이름은 모두 식별자**다. 이 모든 이름은 네이밍 규칙을 준수해야 하며, **선언 declaration**에 의해 자바스크립트 엔진에 식별자의 존재를 알린다.

## 4.3 변수 선언

변수 선언은 **메모리 공간을 확보**하고 **변수 이름과 관련된 확보된 메모리 공간의 주소를 연결**해서 **값을 저장할 수 있게 준비**하는 것, 즉 변수를 생성하는 것이다.

변수를 사용하기 위해서는 반드시 선언이 필요하고 var, let, const 의 키워드를 사용한다.

{% hint style="success" %}
**+ var 키워드**의 대표적인 **단점**은 **블록 레벨 스코프를 지원하지 않고 함수 레벨 스코프를 지원**한다는 것이다. 이로 인해 의도치 않게 전역 변수가 선언되는 오류가 발생한다. ES6에서 let , const의 키워드를 도입한 이유는 var의 여러 단점을 보완하기 위해서다.

\+ **\[키워드]**&#xB294; 자바스크립트 코드를 해석하고 실행하는 자바스크립트 엔진이 수행할 동작을 규정한 일종의 **명령어**다.&#x20;
{% endhint %}

JS 엔진의 변수 선언은 다음 **두 단계**를 거처 수행한다.

1. **선언 단계** : 변수 이름을 등록해서 엔진에 변수의 존재를 알린다.
2. **초기화 단계** : 값 저장을 위해 메모리를 확보하고 암묵적으로 undefined를 할당한다.

## 4.4 변수 선언의 실행 시점과 변수 호이스팅&#x20;

JS에서는 변수 선언문보다 앞에서 변수를 참조해도 에러가 발생하지 않는다.&#x20;

이 현상은 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 과정인 **런타임이 아니라**, 그 **이전 단계에서 먼저 실행**되기 때문이다.&#x20;

JS엔진은 런타임 이전에 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 한다. 이 때 변수 선언을 포함한 모든 선언문을 소스코드에서 찾아내 먼저 실행한다. 따라서 변수 선언이 소스코드의 어디에 있든 상관없이 다른 코드보다 먼저 실행된다.

이렇게 **변수 선언문이 코드의 선두에 끌어 올려진 것처럼 동작하는** 자바스크립트의 고유의 특징을 **\[변수 호이스팅]** 이라고 한다.

## 4.5 값의 할당

변수 선언과 값을 할당은 따로 표현할 수도 있고, 하나의 문으로 단축 표현될 수도 있다.&#x20;

```javascript
var score;  // 변수 선언
score = 80; // 값의 할당
// 혹은 
var score = 80; // 변수 선언과 값의 할당
```

표현 방법과 상관없이 2 개의 문으로 나누어 각각 실행한다.

1. **\[변수 선언]**&#xC740; **런타임 이전**에 먼저 실행되지만&#x20;
2. **\[값의 할당]**&#xC740; 소스코드가 순차적으로 실행되[^1]는 **런타임에 실행**된다.

변수 선언 시에는 undefined로 할당되어 초기화하고, 값의 할당 시점에 새로운 메모리 공간을 확보하고 그곳에 값을 저장하고 변수의 참조를 변경한다.

## 4.6 값의 재할당

var 로 선언한 변수는 값 재할당이 가능하다. **재할당이 불가능하다면 \[상수]이며 const 키워드를 사용해 상수를 표현**할 수 있다.&#x20;

값을 재할당하면 기존의 메모리 공간을 지우고 그 메모리 공간에 재할당한 값을 넣는 것이 아니라, 새로운 메모리 공간을 확보하고 그 공간에 새로운 값을 저장하고 변수가 새로운 메모리를 참조하도록 한다. 향후 아무도 참조하지 않는 메모리는 \[가비지 콜렉터]에 의해서 메모리에서 자동 해제된다. 단, 언제 메모리에서 해제될지는 알 수 없다.

\[가비지 콜렉터] - 애플리케이션이 할당한 메모리 공간을 주기적으로 검사, 더이상 사용되지 않는 메모리를 해제하는 기능이며 이로 인해 메모리 누수를 방지한다.

## 4.7 식별자 네이밍 규칙&#x20;

* 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어(\_), 기호($)를 포함할 수 있다.
* 단, 숫자로 시작하는 것은 허용되지 않는다.
* \[예약어]는 식별자로 사용할 수 없다.

{% hint style="info" %}
\+ \[예약어] - 프로그래밍 언어에서 사용되고 있거나, 사용될 예정인 단어를 말한다.
{% endhint %}

**\[네이밍 컨벤션]**&#xC740; 하나 이상의 영어 단어로 구성된 식별자를 만들 때 가독성 좋게 단어를 한눈에 구분하기 위해 규정한 명명 규칙이다.

```javascript
// 카멜 케이스 (camelCase)
var firstName;

// 스네이크 케이스 (snake_case)
var first_name;

// 파스칼 케이스 (PascalCase)
var FirstName;

// 헝가리언 케이스 (typeHungarianCase)
var strFirstName; // type + identifier
var $elem = document.getElementById('myId'); // DOM 노드
var observable$ = fromEvent(document, 'click'); // RxJS 옵저버블
```

자바스크립트는 일반적으로 변수나 함수의 이름에는 카멜 케이스를 사용하고,

생성자 함수, 클래스의 이름에는 파스칼 케이스를 사용한다.

[^1]:
