컴퓨터(자바스크립트 엔진)가 자바스크립트 코드를 실행하고 계산하려면 그 식이 가진 기호(ex. 10, 20, +)들의 의미, 표현식(10+20)의 의미를 해석할 수 있어야 한다.
메모리: 데이터를 저장할 수 있는 메모리 셀의 집합체
메모리 셀
메모리가 데이터를 저장하는 방. 메모리 셀 하나의 크기는 1바이트(8bit). 컴퓨터는 메모리 셀의 크기(1바이트) 단위로 데이터를 저장하거나 읽어들인다.
메모리 주소
메모리 공간의 위치. 0부터 시작해서 메모리 크기만큼 정수로 표현한다. 모든 데이터는 그 데이터의 형태가 어떻든 모두 2진수로 저장하고 처리한다.
CPU: 연산
변수 이름을 식별자라고도 한다. 또한 함수, 클래스 등 어떤 값을 식별할 수 있는 이름은 모두 식별자라고 한다.
어떤 값을 구별해서 식별할 수 있는 고유한 이름
메모리 공간에 저장되어 있는 어떤 값을 구별해서 식별해내기 위해, 그 메모리 주소를 기억하고 있어야 한다.
메모리 공간에 저장되어 있는 어떤 값을 구별해서 식별해내기 위해, 그 메모리 주소를 기억하고 있어야 한다.
즉, 식별자는 값이 저장되어 있는 메모리 주소와 매핑 관계를 맺으며, 매핑 정보도 메모리에 저장되어야 한다. → 식별자는 값 자체가 아니라 메모리 주소를 기억한다.
식별자는 네이밍 규칙을 준수해야 한다(뒤에서 다룰 예정).
자바스크립트 엔진에 식별자의 존재를 알리기 위해서는 ‘선언’이라는 과정이 필요하다.
호이스팅
최근 var 키워드가 잘 안 쓰이는 이유
1) 함수 레벨 스코프
- 함수 내에서 선언된 변수는 함수 내에서만 유효하다. 따라서, 함수 외부에서 선언한 변수는 모두 전역 변수가 된다. 전역 변수는 전역 객체의 속성으로 간주되기 때문에 전역 객체의 생명주기, 즉 웹페이지를 닫을 때까지 계속 메모리를 차지한다. 쓰지 않을 때도 메모리를 계속 차지하고 있게 되므로 리소스 관리에 비효율적이다.
- cf) 블록 레벨 스코프: {}로 묶인 코드 블록(ex. if문, for문 … 물론 함수도 포함됨) 내에서 선언된 변수는 해당 블록 안에서만 유효하다(ex. C언어에서 for(int i = 0; i<5; i++)라고 for문을 돌렸을 때, for문 밖에서 i 참조 불가). 변수가 유효할 수 있는 단위가 함수 레벨 스코프보다 더 자잘하기 때문에 변수의 생명 주기를 단축시킬 수 있어 메모리 관리에 더 효율적이다.
2) var 키워드 생략 가능
- var 키워드를 생략 가능하기 때문에 의도치 않은 전역변수를 양산할 수 있다.
3) 변수 중복 선언 허용
var a = 1; 라고 처음에 선언해 놓고,
var a = 2; 이렇게 밑에서 동일한 변수를 똑같이 선언해도 오류를 내지 않는다. 이 경우 가장 최근에 선언한 var a = 2;를 참조하기 때문에 개발자의 의도와 다르게 프로그램이 흘러갈 수 있다. (let, const의 경우 변수 중복 선언 시 오류를 냄)4) 변수 호이스팅
- 호이스팅: 변수, 함수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 방식
- var은 let과 다르게 선언 단계와 초기화 단계가 동시에 이루어져 코드 자체의 가독성을 떨어뜨리고, 변수의 초기화 순서에 혼란을 일으킨다.
- 뒤에서 더 자세히 다룰 예정
5) TDZ(Temporal Dead Zone)
- let이랑const는 선언만 되고, undefined라는 값의 할당은 실행 시점에 되기 때문에 초기화 전에 변수를 사용해 버리면 프로그램에서 reference error을 내 준다. 따라서 코드를 예측 가능하게 하고 잠재적 버그를 줄인다. 그런데 var 키워드는 호이스팅 단계에서 초기화까지 진행해 버리므로 프로그램이 오류를 내 주지 않는다.
- var 키워드를 사용한 변수 선언은 선언 단계와 초기화 단계가 동시에 진행된다. 즉, var score;라고 선언하면 해당 변수를 위한 메모리 공간이 확보되고 거기에 변수 이름 score을 등록함과 동시에 해당 공간에 undefined라는 값이 할당(초기화)된다.
- 초기화 단계를 거치지 않으면 이전에 다른 애플리케이션이 사용했던 값(=쓰레기값)이 남아있을 수 있다.
- 선언하지 않은 식별자에 접근하면 참조 에러가 발생한다.
console.log(score);
var score;
console.log(score);
//score = 80;
var score = 80;
console.log(score);
var score; //undefined
let score; //선언만
console.log('할당 이전: '+score); //참조 에러
score = 80;
console.log('할당 이후: '+score);
let과 const는 선언만 호이스팅된다 (var의 문제점 4번 보완)
변수를 선언하는 시점부터 변수를 사용하는 것이 자연스러운데, 변수 선언만 먼저 위로 끌어올리는 호이스팅 방식 때문에 선언되기 전의 변수를 사용하는 등의 코딩이 가능했다. 이런 코딩 방식이 개발자 입장에서 코드의 가독성을 떨어뜨리고, 실행 순서를 혼란스럽게 만든다는 지적이 발생하면서 ES6부터 새로 생긴 let과 const 키워드를 이용한 변수는 선언만 호이스팅되어 위로 끌어올려지고, undefined는 실행 시점에 초기화된다.
가비지 콜렉터란?(Garbage Collector)
가비지 콜렉터는 메모리 공간을 주기적으로 검사하여 더 이상 사용되지 않는 메모리를 해제하는 기능을 애기한다. 자바스크립트는 매니지드 언어로서 개발자가 직접 메모리 제어를 할 수 없어 가비지 콜렉터를 통해 메모리 누수를 방지한다.
단점
- 언제 가비지 컬렉션이 진행될지 예측하기 어렵다.
- 객체가 쓸모 없어지는 시점에 정확히 메모리가 해제되지 않기 때문에 최적의 메모리 관리가 되지 않는다.
- 가비지 컬렉터가 동작하는 시간이 든다.
- 어떤 객체가 쓸모 없는지 판단하는 시간이 소요된다.
카멜 케이스
var firstName;
스네이크 케이스
var first_name;
파스칼 케이스
var FirstName;
헝가리언케이스
var strFirstName; //type + identifier
책에서는 카멜 케이스, 파스칼 케이스 추천