변수
데이터를 관리하기 위한 핵심 개념.
자바스크립트 엔진이 다음의 코드를 평가하는 과정은 다음과 같다.
10 + 20
메모리
데이터를 저장할 수 있는 메모리 셀 (Memory Cell)의 집합체.
메모리 셀 하나의 크기: 1바이트 (8비트).
컴퓨터는 메모리 셀의 크기 (1바이트) 단위로 데이터를 저장 (Write) 하거나 읽어 (Read) 들인다.
메모리 주소
각 셀은 고유의 메모리 주소를 갖는다.
예시
4GB 메모리는 0부터 4,294,967,295 (0x00000000 ~ 0xFFFFFFFF) 까지의 메모리 주소를 갖는다.
데이터는 메모리 상의 임의의 위치 (메모리 주소)에 기억 (저장).
10 + 20
메모리 상의 값을 사용하려면 메모리 공간에 직접 접근해야 한다.
자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.
메모리 상에 직접 접근면 치명적 오류 발생 가능.
코드가 실행될 때마다 메모리 주소는 변경된다.
코드가 실행되기 전에는 메모리 주소를 알 수 없어서 접근이 불가능.
따라서, 메모리 상의 값을 불러올 수 있는 매개체가 필요하다.
변수
- 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 식별하기 위해 붙인 이름.
- 값을 저장하고 참조하는 매커니즘.
- 값의 위치를 가리키는 상징적인 이름.
변수는 컴파일러 또는 인터프리터에 의해 해당 메모리 주소로 치환되어 실행.
변수를 통해 값에 안전하게 접근 가능.
// 변수는 하나의 값을 저장하기 위한 수단이다.
var userId = 1;
var userName = 'Lee';
// 객체나 배열 같은 자료구조를 사용하면 여러 개의 값을 하나로 그룹화해서 하나의 값처럼 사용할 수 있다.
var user = { id: 1, name: 'Lee' };
var users = [
{ id: 1, name: 'Lee' },
{ id: 2, name: 'Kim' }
];
메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름.
변수 이름과 매핑된 메모리 주소를 통해 메모리 공간에서 값을 불러온다.
저장된 값의 의미를 내포하여 가독성을 높일 수 있다.
변수에 저장된 값.
변수에 값을 저장하는 것.
변수에 저장된 값을 읽어 들이는 것.
식별자
- 어떤 값을 구별 및 식별할 수 있는 고유한 이름.
- 값이 저장되어있는 메모리 주소와 매핑 관계를 맺는다.
- 이 매핑 정보 역시 메모리에 저장.
- 값이 아니라 메모리 주소를 기억한다.
메모리 상에 존재하는 값을 식별할 수 있는 이름은 모두 식별자. (변수, 함수, 클래스 등)
변수 이름 : 메모리 상에 존재하는 변수 값을 식별.
함수 이름 : 메모리 상에 존재하는 함수를 식별.
변수 선언
변수를 생성하는 것.
값을 저장하기 위해 메모리 공간을 확보 (Allocate).
변수 이름과 확보된 메모리 공간의 주소를 연결 (Name Binding).
확보가 해제 (Release)되기 전까지는 안전하게 사용 가능.
변수를 선언할 때는
var
,let
,const
키워드를 사용.
키워드 (Keyword)
자바스크립트 엔진이 코드를 해석, 실행하도록 동작을 규정한 명령어.
ES5까지는 var
만 존재.
var
의 단점 (스코프, 호이스팅)을 보완하여 ES6부터 let
, const
가 등장.
var score; // 변수 선언(변수 선언문)
변수 선언문을 만나면 변수 이름을 등록하고 값을 저장할 메모리 공간을 확보한다.
확보된 메모리 공간은 자동으로 undefined
가 할당되어 초기화. (자바스크립트의 특징)
변수 이름을 등록해서 자바스크립트 엔진에 변수 존재를 알린다.
변수 이름은 실행 컨텍스트 (Execution Context) 에 저장. (23장에서 계속)
값을 저장하기 위한 메모리 공간 확보.
메모리 공간 확보 후 최초의 값을 할당.
초기화를 하지 않으면 메모리 공간에 이전 어플리케이션에서 사용했던 값 (쓰레기 값, Garbage Value)이 남아있을 수 있다.
자바스크립트 엔진이 등록된 식별자를 찾을 수 없을 때 발생하는 에러.
선언 단계와 초기화 단계가 동시에 진행.
var
는 초기화 단계에서 자동으로 undefined
할당.
console.log(score); // undefined
var score; // 변수 선언문
score
선언 이전에 console.log()
가 있으므로 ReferenceError
가 뜰 것 같지만 undefined
가 뜬다.
변수 선언이 런타임 이전 단계에서 먼저 실행되기 때문.
런타임 (Runtime)
소스코드가 한 줄씩 순차적으로 실행되는 시점.
자바스크립트 엔진은 소스코드를 실행하기 전에 소스코드를 평가.
평가 과정에서 모든 선언문 (변수, 함수 등)만 찾아서 먼저 실행. (어디에 있던지 상관 없이) 평가 과정이 끝나면 모든 선언문을 제외한 나머지 코드를 한 줄씩 실행.
var
에서 소스코드 평가var
는 변수 선언과 동시에 undefined
로 초기화되기 때문에, 선언문 이전에 console.log
를 만나도 undefined
가 출력.
호이스팅
선언문의 코드의 최상단으로 끌어 올려진 것처럼 동작하는 현상.
모든 선언문은 런타임 이전 단계에서 먼저 실행되기 때문.
var
의 경우처럼 선언문 이전에 접근이 가능한 경우를 호이스팅이라고 한다.
var
, let
, const
, function
, function*
, class
키워드 등 모든 식별자는 호이스팅된다.
할당 연산자 (=
)를 통해 변수에 값을 할당 (Assignment)할 수 있다.
변수 할당은 2개 또는 1개의 문 (Statement)으로 할 수 있다.
var score; // 변수 선언
score = 80; // 값의 할당
var score = 80; // 변수 선언과 값의 할당
어떻게 작성해도 자바스크립트 엔진은 변수 선언과 값의 할당을 항상 2개의 문으로 나누어 각각 실행.
변수 선언은 런타임 이전에 실행되고 값의 할당은 런타임에 실행.
console.log(score); // undefined
var score; // ① 변수 선언
score = 80; // ② 값의 할당
console.log(score); // 80
재할당
이미 값이 할당되어 있는 변수에 새로운 값을 또 다시 할당하는 것.
var score = 80; // 변수 선언과 값의 할당
score = 90; // 값의 재할당
var
, let
은 재할당이 가능.
상수 (Constant)
값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없는 변수.
const
키워드를 사용해 선언 가능.
재할당은 기존의 메모리 공간을 지우고 새로운 값을 할당하는 것이 아닏.
기존의 메모리 공간은 그대로 두고, 새로운 메모리 공간에 값을 할당.
score
변수에 90이 재할당되었으므로, undefined
와 80은 더 이상 필요하지 않은 쓰레기 값 (Garbage Value)이 됨.
쓰레기 값은 가비지 콜렉터 (Garbage Collector)에 의해 자동으로 메모리에서 해제 된다.
카비지 콜렉터
어플리케이션이 할당한 메모리 공간을 주기적으로 검사하여, 더 이상 사용되지 않는 메모리를 해제하는 기능.
사용되지 않는 메모리
어떤 식별자도 참조하지 않는 메모리 공간.
자바스크립트는 가비지 콜렉터를 내장하고 있는 매니지드 언어 (Managed Language).
자동으로 가비지 콜렉터를 동작하여 메모리 누수 (Memory Leak)를 방지.
언매니지드 언어 (Unmanaged Language)
개발자가 malloc(), free() 등의 저수준의 메모리 제어 기능을 통해, 직접 메모리 할당 및 해제가 가능.
매니지드 언어 (Managed Language)
메모리 관리는 언어가 담당하고 개발자의 직접적인 제어를 비허용.
식별자는 다음과 같은 네이밍 규칙을 준수해야 한다.
예약어
프로그래밍 언어에서 사용되고 있거나 사용될 예정인 단어.
var 이름, なまえ;
// 불가능
var first-name; // SyntaxError: Unexpected token –
var 1st; // SyntaxError: Invalid or unexpected token
var this; // SyntaxError: Unexpected token this
// 대소문자를 구별.
// 서로 다른 변수.
var firstname;
var firstName;
var FIRSTNAME;
네이밍 컨벤션
가독성 좋게 단어를 한눈에 구분하기 위한 명명 규칙.
var firstName;
var first_name;
var FirstName;
var strFirstName; // type + identifier
var $elem = document.getElementById('myId'); // DOM 노드
var observable$ = fromEvent(document, 'click'); // RxJS 옵저버블