Javascript

JavaScript에서 변수란 무엇일까?

Yepchani 2023. 9. 25. 18:57

들어가며

이번 시간에는 가장 기본이 되는 개념 중 하나인 변수에 대해 간단히 알아보도록 하겠습니다.


변수란 무엇인가

변수는 하나의 값을 저장하는 메모리 공간을 가리키는 이름입니다.

변수는 식별자이기도 한데요. 식별자란 무언가(변수, 함수, 클래스 등)를 식별하기 위한 이름입니다.

우리가 어떤 값을 쓰고자 한다면 먼저 변수를 선언하고 값을 할당해주어야 합니다.

 

변수 선언이란 변수를 생성하는 것을 말합니다. 값을 저장할 수 있는 크기만큼의 메모리 공간을 확보하고,

확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있도록 준비하는 건데요. 이렇게 확보된 공간은 해제되기 전까지 누구도 사용할 수 없도록 보호되어 안전합니다.

자바스크립트 엔진은 변수 선언을 다음과 같은 2단계에 걸쳐 수행합니다.

  • 선언 단계: 실행 컨텍스트에 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알립니다.
  • 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고, undefined를 할당해 초기화합니다. 해당 변수의 값이 아직 정의되지 않았다는 뜻이죠!

이렇게 선언된 변수가 가리키는 메모리 공간에 값이 할당되어 저장됩니다.

 

이제 우리는 원하는 곳에서 변수를 참조해 값을 재사용 할 수 있게 되었네요!

 

var foo = 1; // 변수를 선언함과 동시에 1을 할당함

console.log(foo); // 1

var bar = foo; // bar에는 foo에 들어있는 1이 할당됨

console.log(bar); // 1

 

변수 선언 키워드

자바스크립트에서 사용할 수 있는 변수 선언 키워드는 var, let, const 총 세 가지가 있습니다.

var

앞서 보신 것처럼 변수를 선언한 이후 값을 할당해줘야 하는데요.

만약 다음과 같이 값을 할당해주지 않은 채로 변수를 참조한다면 어떻게 될까요?

 

var foo;

console.log(foo);

undefined가 출력됩니다.

어라, 우린 undefined라는 값을 할당해 준 적이 없는데 어떻게 된 걸까요?

 

var를 사용해 변수를 선언하면 선언 단계와 초기화 단계가 동시에 진행되는데요. 초기화 단계에서 변수에 암묵적으로 undefined가 할당됩니다.

 

이번엔 다른 상황을 한번 볼까요?

만약 변수 선언 이전에 해당 변수를 참조하려고 한다면 어떻게 될까요? ReferenceError가 발생할까요?

 

console.log(foo);

var foo = 1;

이번에도 undefined가 출력됩니다.

아니 어째서죠? 에러가 발생하는 것도 아니고 말이죠!

 

여기서 "호이스팅"이라는 개념이 등장합니다.

호이스팅이란 "변수나 함수 선언문이 해당 스코프의 최상단으로 끌어올려진 것처럼 동작하는 것"을 의미하는데요. 선언문은 가장 먼저 실행되고, 따라서 선언문 이전에 해당 변수에 접근하거나 함수를 호출할 수 있습니다.

스코프는 "식별자를 참조할 수 있는 유효한 범위"라고 간단히 이해하고 넘어가겠습니다.

 

현재 코드에서 foo의 스코프는 코드 전체입니다.

호이스팅이 일어난 후의 코드는 다음과 같이 동작합니다.

 

var foo; // undefined로 초기화

console.log(foo) // undefined

foo = 1;

보시다시피 변수 선언문은 최상단으로 끌어올려졌지만, 할당문은 그 자리에 남아있는 모습을 보실 수 있습니다.

 

그럼 아래 코드의 결과는 어떻게 될까요?

 

console.log(foo); // undefined

foo = 80;

var foo;

console.log(foo) // ??

지금 콘솔 창을 켜서 한번 실행해보시기 바랍니다.

 

var은 값의 재할당이 가능합니다.

 

var foo = 1;

console.log(foo); // 1

foo = 2;

console.log(foo); // 2

먼저 1을 할당하고 나서 2를 할당하고 출력을 하게 되면 나중에 할당된 값인 2로 바뀌게 됩니다.

 

let

let은 값의 재할당이 가능합니다.

 

let foo = 1;

console.log(foo); // 1

foo = 2;

console.log(foo); // 2

let을 사용해 변수를 선언하면 선언 단계와 초기화 단계가 분리되어 진행됩니다. 따라서 초기화 전에 접근하려 하면 ReferenceError가 발생합니다.

let으로 선언한 변수는 스코프의 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조할 수 없는데요. 이 구간을 TDZ(Temporal Dead Zone)라고 부릅니다.

 

console.log(foo); // Uncaught ReferenceError: foo is not defined

let foo;
console.log(foo); // undefined

foo = 1;
console.log(foo); // 1

이렇게 보면 언뜻 let으로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 보이는데요. 그렇지 않습니다.

 

let foo = 1; // 전역 변수

{
  console.log(foo); // Uncaught ReferenceError: Cannot access 'foo' before initialization
  let foo = 2; // 지역 변수
}

만약 호이스팅이 발생하지 않는다면 위의 예제에서 전역 변수 foo의 값인 1을 출력해야 합니다. 하지만 여전히 호이스팅이 발생하기 때문에 ReferenceError가 발생하죠.

 

const

const는 값의 재할당이 불가능하므로 선언과 동시에 값을 할당해주어야 합니다. 그렇지 않으면 에러가 발생합니다.

 

const foo; // Uncaught SyntaxError: Missing initializer in const declaration

const bar = 2;

bar = 3; // Uncaught TypeError: Assignment to constant variable.

const는 상수를 할당할 수 있는데요. 상수는 값이 변하지 않는 값을 담은 변수를 말하며, 일반적으로 대문자로 표시합니다.

 

const INCH_TO_CENTIMETER = 2.54;

console.log(INCH_TO_CENTIMETER); // 2.54

const도 let과 같이 TDZ 개념이 적용되어 초기화 전에 변수에 접근할 수 없습니다.

 

console.log(foo); // Uncaught ReferenceError: foo is not defined

const foo = 1; 

console.log(foo); // 1

 


마치며

여기까지 변수에 대해서 간단히 알아보았는데요.

이해하시는데 조금이라도 도움되었으면 좋겠습니다.

 

잘못된 부분은 지적 부탁드립니다.

감사합니다 :D