본문 바로가기
언어 Language/자바스크립트 JavaScript

[JavaScript] 변수 (선언, 초기화, 할당, let, var, const, 스코프)

by 이땡칠 2022. 6. 13.

 

변수(Variable)

 

요약


변수
는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름인 식별자를 말합니다. 
상수는 변수처럼 이름을 붙인 값이지만, 변수와 달리 상수의 값은 바꿀 수 없습니다.

변수 선언 단계
자바스크립트 엔진은 변수 선언을 선언과 초기화 2단계로 수행합니다. 
1. 선언 단계: 변수명을 등록하여 자바스크립트 엔진에 변수의 존재를 알린다.
2. 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.


var, let, const 의 공통점 & 차이점
1. var와 let 키워드는 변수를 선언할 때 사용되며, const 키워드는 상수를 선언할 때 사용됩니다.

2. let, const는 블록 레벨 스코프, var는 함수 레벨 스코프를 따릅니다.
 - let, const 로 선언한 식별자는 자신을 선언한 블록과 모든 하위 블록을 스스로의 스코프로 가집니다.
 - 반면, var의 스코프는 '자신을 선언한 블록'이 아니라, 자신의 선언을 포함하는 함수의 스코프를 자신의 스코프로 가집니다.

3. let 으로 선언한 변수는 mutable data type 이기 때문에 변수에 재할당이 가능하고, const 으로 선언한 상수는 immutable data type 이기 때문에 재할당이 불가합니다.

4. let은 선언하고 나중에 값 할당이 가능하지만, const는 선언과 동시에 값을 할당해야 합니다.

1. 변수는 무엇인가?

  • 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말합니다. 
  • 값의 위치를 가리키는 상징적인 이름입니다.
  • 변수는 프로그래밍 언어의 컴파일러 or 인터프리터에 의해 값이 저장된 메모리 공간의 주소로 치환되어 실행됩니다. 
  • 자바스크립트는 매니지드 언어(managed language)이기 때문에 개발자가 직접 메모리를 제어하지 못합니다. 따라서 개발자가 직접 메모리 주소를 통해 값을 저장하고 참조할 필요가 없고 변수를 통해 안전하게 값에 접근이 가능합니다.

 

 

const myNumber = 23
// 변수명(식별자): myNumber
// 해당 값의 위치(메모리 주소): 0012CCGWH80
// 변수 값(저장된 값): 23

 

변수명(식별자)인 myNumber는 변수의 값이 아닌 메모리 주소를 기억하고 있습니다. 변수명을 사용하면, 자바스크립트 엔진이 변수명과 매핑된 메모리 주소를 통해 거기에 저장된 값(23)을 반환합니다.

 

 

2. 식별자

  • 변수를 부르는 다른 말입니다.
  • 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말합니다. 
  • 식별자는 어떤 값을 구별해서 식별하기 위해 메모리 주소를 기억해야 하기 때문에, 메모리 주소와 매핑 관계를 맺으며, 이 매핑 정보도 메모리에 저장되어야 합니다.

 

3. 변수 선언

  • 변수의 선언은 var, let 키워드로 할 수 있으며, ES6에서 let이 추가되었습니다.
  • 자바스크립트에서 변수 선언은 선언 → 초기화 단계를 거쳐 수행됩니다.
    • 선언 단계: 변수명을 등록하여 자바스크립트 엔진에 변수의 존재를 알린다.
    • 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.
var lee
console.log(lee) // undefined
  • [참고] 할당, 참조
    • 할당(assignment, 대입, 저장)은 변수에 값을 저장하는 것입니다.
    • 참조(reference)는 변수에 저장된 값을 읽어 들이는 것입니다.

 

 

4. 변수 선언의 실행 시점과 호이스팅

 

  • 자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하는 런타임에 앞서, 먼저 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 합니다.
  • 이 평가 과정에서 변수 선언을 포함한 모든 선언문(ex. 변수 선언문, 함수 선언문 등)을 찾아내 실행합니다.  이를 "호이스팅(hoisting)"이라고 부릅니다.
// hoisting으로 인해 ReferenceError 에러가 나지 않고 undefined 가 출력된다.

console.log(age);  // undefined
age = 4;		   
console.log(age); // 4
var age;

 

5. 값의 할당

  • 변수에 값을 할당할 때는 연산자 = 를 사용합니다.
  • 변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행됩니다.
  • 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행됩니다. 
  • (주의) 변수에 값을 할당할 때는 이전 값 undefined 가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값을 새롭게 저장하는 게 아니라, 새로운 메모리 공간을 확보하고 그곳에 할당 값을 저장합니다.

 

 

6. 값의 재할당

  • 재할당은 현재 변수에 저장된 값을 버리고 새로운 값을 저장하는 것입니다. 
  • var, let 으로 선언한 변수는 재할당이 가능합니다. 
  • 재할당 시 새로운 메모리 공간을 확보하고 그 메모리 공간에 새로운 값을 저장합니다. 
가비지 콜렉터

어떤 식별자와도 연결되지 않은, 아무도 사용하고 있지 않은 값들은 가비지 콜렉터에 의해 메모리에서 자동 해제됩니다. 단, 메모리에서 언제 해제될지는 예측할 수 없습니다.
자바스크립트는 가비지 콜렉터를 내장하고 있는 매니지드 언어로서, 가비지 콜렉터를 통해 메모리 누수를 방지합니다. 
매니지드 언어
매니지드 언어는 메모리의 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당하고 개발자의 직접적인 메모리 제어를 허용하지 않습니다. 
매니지드 언어는 개발자의 역량에 의존하는 부분이 상대적으로 작아져 어느 정도 일정한 생산성을 확보할 수 있다는 장점이 있지만, 성능 면에서 어느 정도의 손실은 감수할 수밖에 없습니다.

 

const와 let의 등장 배경 

var는 블록 레벨 스코프를 지원하지 않아, 블록을 무시합니다. (Non block-level scope)

  • var는 함수 레벨 스코프를 지원하고, 블록 레벨 스코프를 지원하지 않습니다.
  • var 키워드를 사용하여 함수 밖에서 선언된 변수는 코드 블록 내에서 선언되었다할지라도 모두 전역 스코프을 갖게 됩니다.
{
 age = 4;
 var age;
}

console.log(age);  // 4

 

블록 안에 선언된 변수를 전역변수처럼 읽어서 콘솔에 4가 출력됩니다.

 

 

 


상수(Constants)

  • 상수 또한 변수처럼 이름을 붙인 값이지만, 변수와 달리 상수의 값은 바꿀 수 없습니다.
  • 상수는 const 키워드로 생성할 수 있습니다.
  • 우리가 변수를 이용하면 변수가 메모리 어딘가에 할당된 박스를 가리키고 있어서 포인터를 이용해서 값을 계속 바꿔나갈 수 있었는데, const 는 가리키고 있는 포인터가 잠겨있어서 값을 선언함과 동시에 할당한 이후는 값을 다시는 변경할 수 없습니다. 
  • 값이 계속 변경될 수 있는 값을 Mutable data type 이라고 합니다. let 키워드를 이용한 변수가 Mutable data type 이고, const 는 변경이 불가능하기 때문에 Immutable data type 이라고 불립니다. 

 

Immutable data type 사용을 선호하는 이유

Immutable data type 사용을 선호하라고 많은 개발자들이 이야기하는데, 그 이유는 다음과 같습니다.

 

  • 먼저, 보안 상 이유입니다. 한번 작성한 값을 다른 해커들이 코드를 이상한 걸 삽입해서 값을 변경해나가는 게 가능한데요, immutable data type 은 그것을 방지할 수 있습니다. 
  • 두번째는 thread safety 입니다. 어플리케이션이 실행되면 한 가지의 프로세스가 할당이 되고, 그 프로세스 안에서는 다양한 thread 가 동시에 돌아가면서 어플리케이션을 조금 더 빠르게 동작할 수 있도록 도와주는데요. 다양한 thread 들이 동시에 변수에 접근에서 값을 변경할 수가 있는데, 동시에 값을 변경할 수 있다는 것은 조금 위험합니다.  
  • 세번째는 사람의 실수를 줄이기 위해서입니다. 내가 나중에 코드를 변경하거나, 다른 개발자가 코드를 바꿀 때에도 실수를 방지해줄 수 있습니다. 

 

 

 

 

 


스코프(Scope)

 

1. 스코프 개념

  • 스코프는 참조 대상 식별자를 찾아내기 위한 규칙으로, 자바스크립트는 이 규칙대로 식별자를 찾습니다.
  • 식별자는 자신이 어디에서 선언됐는지에 의해 자신이 유효한(다른 코드가 자신을 참조할 수 있는) 범위를 갖습니다. 이를 렉시컬 스코프라고 합니다.

 

2. 블록 레벨 스코프(block-level scope) 

  • 블록 레벨 스코프란 코드 블록({…})내에서 유효한 스코프를 의미합니다.
  • 여기서 “유효하다”라는 것은 “참조(접근)할 수 있다”라는 뜻입니다.

 

3. 함수 레벨 스코프(function-level scope)

  • 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것입니다.

 

 

 

 

 

참고 

var, let, const의 차이 ⏤ 변수 선언 및 할당, 호이스팅, 스코프

자바스크립트 3. 데이터타입, data types, let vs var, hoisting | 프론트엔드 개발자 입문편 (JavaScript ES5+)

[mdn] JavaScript 에 발 담그기

[mdn] JacaScript guide

var, let, const 차이점은?

[JavaScript] ES6 블록 레벨 스코프에 대해 알아보자!! (feat.let, const)

 

댓글