변수와 호이스팅

황희윤·2021년 10월 20일
0

변수를 알아보기 앞서서...

컴퓨터는 CPU를 통해서 연산하고, 메모리를 사용해 기억한다.

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

각 셀은 고유의 메모리 주소를 갖고, 이 메모리 주소메모리 공간의 위치를 나타내며, 0부터 시작해서 메모리 크기만큼 정수로 표현된다.

만약 10 + 20 이라는 계산을 수행하면, 10과 20은 메모리 상의 임의의 위치에 기억(저장)되고, CPU는 이 값을 읽고 연산을 수행한다. 연산 결과로 생성된 결과 값 30도 메모리 상의 임의의 위치에 저장된다.

하지만 여기서 만들어낸 결과 값 30을 재사용할 수 없다. 재사용하려면 30이 들어있는 임의의 메모리 주소를 찾아 메모리 공간에 직접 접근해야 하지만, 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다. 왜냐하면, 메모리 주소에 잘못 접근해서 수정하게 되면 시스템을 멈추게 할 수도 있기 때문이다.

또한 동일한 CPU에 동일한 코드를 쳐도 값은 그때 그때 다른 임의의 주소에 저장되어서, 코드를 실행한 후에만 임의의 주소를 알 수 있다.

변수

변수는 값을 저장한 메모리 공간을 식별하기 위해 붙인 이름으로 값의 위치를 가리킨다.

변수 = 메모리 공간의 주소

변수를 사용하는 이유

값을 재사용하기 위해서

메모리 값이 저장된 임의의 주소에 직접 제어하는 것은 오류를 범할 위험이 크고, 코드가 실행된 이후에야 임의의 주소를 파악할 수 있음.

용어 설명

할당(assignment) : 변수에 값을 저장

참조(reference) : 변수의 값을 읽는

식별자(identifier) : 변수 이름. 메모리 값이 아닌 주소를 기억함.

초기화(initialization) : 변수가 선언된 이후 처음으로 값을 할당하는 것으로 암묵적으로 undefined를 할당해 초기화한다.

변수 선언(declaration) : 변수 생성. 메모리 공간을 확보하고 변수 이름과 메모리 주소를 연결.

자바스크립트 엔진은 소스코드를 한 줄 씩 순차적으로 실행하기에 앞서, 먼저 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 한다. 소스코드의 평가 과정에서 모든 선언문(var, let, const, function, class)을 먼저 실행한다.

변수 호이스팅 : 변수 선언문이 코드의 선두로 끌어올려진 것처럼 동작. 그래서 변수를 선언하기도 전에 코드가 작동될 수 있음.

값의 재할당 : 이미 값이 할당되어 있는 변수에 새로운 값을 할당.

var 키워드로 선언한 변수는 선언과 동시에 맨 처음 undefined 값을 가져서, 엄밀히 말하면 변수에 처음으로 값을 할당하는 것도 재할당이다.

상수(constant) : 한번 정해지면 수정할 수 없는 값

가비지 컬렉터(Garbage Collector) : 메모리 공간을 주기적으로 검사해서, 더 이상 사용되지 않는 메모리를 해제하는 기능.

변수를 선언하는 방법 세가지 키워드

1. var

  • 가장 처음 만들어진 변수 선언 방법

  • 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계와 초기화 단계가 한번에 진행된다.

  • 변수 중복 선언 가능 : 똑같은 이름의 변수가 있는지 모르고 변수를 중복 선언한다면, 먼저 선언된 변수의 값이 바뀔 수도 있다.

  • var는 전역 변수(global variable)와 지역 변수(local variable)의 구분이 애매해, 전역 변수처럼 프로그램 전체에서 실행 가능하다. 함수 내부에 위치하더라도 함수 외부에서도 실행 가능하다.

2. let

  • var의 단점을 보완하기 위해 나온 새로운 변수 선언 방법

  • 중복 선언 금지

  • 선언 단계와 초기화 단계가 분리되어 진행된다.

  • 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계가 먼저 실행되지만, 초기화 단계는 변수 선언문에 도달했을 때 실행된다.

  • TDZ (temporal dead zone) : 초기화 단계 이전에 변수를 참조(read)할 수 없는 구간.

// 런타임 이전에 선언 단계가 실행되고, 아직은 변수가 초기화(initialize)되지 않았다.
// 초기화 이전의 TDZ에서는 변수를 읽을 수 없다.
console.log(fruit); // ReferenceError

let fruit; // 초기화 됨. undefined 할당됨.
console.log(fruit); // undefined

fruit = 'apple'; // 값이 할당됨
console.log(fruit) // apple
  • let은 전역 변수와 지역 변수의 구분이 명확하다.

  • let도 호이스팅이 되지만, 호이스팅이 발생하지 않는 것처럼 동작한다.

let fruit = 'apple'; // 전역 변수
{
  console.log(fruit); // Reference error. 만약 호이스팅이 안되었다면 fruit의 값은 apple이다.
  let fruit = 'orange'; // 지역 변수
}

3. const

  • 재할당 금지 : 한번 원시 값을 할당하면, 변수 값을 변경할 수 없다.

  • 하지만, const에 객체를 할당한 경우 자유롭게 변경 가능하다.

  • const는 반드시 선언과 동시에 값을 할당해야 한다.

요약

호이스팅(hoisting)

  • 코드 런타임 이전에 자바스크립트 엔진에 의해 모든 선언문을 먼저 메모리에 저장하고, 코드 실행 이전에 선언문이 프로그램 맨 위로 끌어올려진 것처럼 동작.

  • 호이스팅으로 인해 var는 undefined를 리턴하고 let과 const는 ReferenceError를 나타낸다.

  • 왜냐하면 var는 런타임 이전에 선언 단계와 초기화 단계가 동시에 실행되어 undefined 값이 할당되지만, let과 const는 TDZ로 인해 undefined 값의 할당을 막아서 값을 참조(read)할 수 없다.

var와 let의 차이점

  • 중복 가능 유무 : var는 중복이 가능하나, let은 불가

let과 const의 차이점

  • 재할당 가능 유무 : let은 재할당이 가능하나, const는 불가. 하지만 const 객체일 때는 재할당 뿐만 아니라 값 수정도 가능하다.

var 호이스팅에서 undefined를 리턴하는 이유

  • 자바스크립트는 코드 실행 이전에 전체적인 코드 평가 과정을 거치는데, 이 평가 과정을 실행 컨텍스트라고 부르고 여기서 프로그램의 모든 선언문들을 미리 메모리에 저장한다. 값은 나중에 코드를 실행할 때 할당하여 리턴한다. 그래서 평가 과정에서는 var 선언문의 값이 undefined로 저장된다.

출처 : 모던 자바스크립트 Deep Dive

profile
HeeYun's programming study

0개의 댓글