자바스크립트에서 변수를 선언할 때에는 반드시 키워드를 앞에 붙여줘야 한다.
파이썬에서는 index = 0 처럼 선언하면 되지만, JS에서는 var index = 0; 이렇게..
변수란?
10 + 20을 계산할 때 사람은 10, 20, +기호를 모두 머릿속에 기억하고 연산도 두뇌로 한다.
그러나 컴퓨터는 저장공간과 연산공간이 다르다.
10, 20은 각각 메모리 셀에 2진수로 기억되고, 각 셀은 고유의 주소를 갖는다.
그리고 메모리 셀에 저장된 값을 CPU라는 곳에서 연산을 한다.
그 연산 결과는 또 어떤 메모리 셀에 들어가게 된다.
이때 결과 셀의 주소를 알아야 다음에 또 참조를 할 수 있는데,
자바스크립트에서 개발자는 주소를 통해 값에 직접 접근할 수 없다.
그래서 '변수'라는 메모리 주소(공간)를 식별하는 이름을 지어 할당해야 한다.
변수를 '식별자'라고 부르기도 하는데, 식별자라는 용어는 변수 이름에만 국한되지 않고
함수, 클래스 등의 이름도 식별자라 부른다.
var, let, const?
자바스크립트 변수 선언 키워드는 var, let, const 세 가지가 있다.
let과 const가 등장하기 전까지는 var 키워드가 자바스크립트에서 유일한 키워드였다고 한다.
그러나 var 키워드는 블록 레벨 스코프를 지원하지 않고, 함수 레벨 스코프를 지원하기 때문에
의도치 않게 전역 변수가 선언되어 부작용이 있어 요즘엔 잘 쓰이지 않는다.
함수 레벨 스코프와 블록 레벨 스코프?
스코프는 '식별자가 유효한 범위'를 뜻한다.
모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 자신을 참조할 수 있는
유효 범위가 결정되며, 이를 스코프라고 한다.
보통 대부분의 프로그래밍 언어는 함수뿐 아니라 모든 코드 블록(if, for 등)에서
지역 변수 할당이 가능한데 이것을 블록 레벨 스코프라고 한다.
반면 자바스크립트의 var의 경우 함수 레벨 스코프(함수 내 변수만 지역 변수 취급)만 지원하며,
블록 레벨에서 정의된 변수는 지역 변수가 아닌 전역 변수 취급한다.
따라서 블록에서 변수를 선언한 경우 전역 변수가 되어버리기 때문에
변수가 많을 경우 중복 선언되어 에러가 발생하기 쉽다.
undefined
자바스크립트에서 키워드를 사용하여 변수를 선언할 때, 변수에 할당할 값을 지정하지 않았을 경우,
예를 들어 var index;라는 코드를 작성했을 경우에
메모리 공간은 확보되지만 그 안에 undefined라는 값이 암묵적으로 초기화되어 할당된다.
초기화란 변수가 선언된 이후 최초로 값을 할당하는 것을 말한다.
만약 초기화 단계를 거치지 않으면 다른 애플리케이션이 사용했던 값이 남아있을 수 있는데,
이런 값을 garbage value라고 한다. 따라서 변수에 값을 할당하지 않은 상태에서 바로 참조한다면
이상한 값이 나올 수 있다. 그러나 var는 암묵적으로 초기화를 수행하기 때문에 안전하다.
변수 호이스팅?
console.log(i);
var i = 10;
이런 코드가 있다. 결과가 어떨까?
JS는 인터프리터 언어로, 한 줄씩 실행된다. 변수 선언보다 실행이 앞서 작성되어 있기 때문에
참조 에러(ReferenceError)가 발생할 것이라 예상된다.
그러나, 자바스크립트는 호이스팅이 동작하기 때문에 결괏값이 undefined로 나온다.
자바스크립트 엔진이 소스코드를 한 줄씩 순차적으로 실행하는 것은 맞지만, 그전에 처리하는 것이 있다.
소스코드 평가 과정을 거치는데, 여기서 변수 선언을 포함해 모든 선언을 코드에서 찾아내 선언한다.
주의할 점은, 변수는 (선언-초기화-할당) 단계를 거치는데
var는 선언과 초기화를 동시에 하는데 비해 let은 선언과 초기화가 분리되어 실행된다.
그리고 소스코드 평가 과정이 끝난 후에 이미 선언된 것들을 제외하고 한 줄씩 순차적으로 실행한다.
따라서 var i;를 먼저 찾아내 선언+초기화했기 때문에 에러가 뜨지 않는 것이다.
그러나 할당은 아직 하지 않았기 때문에 초기화 값인 undefined가 나온다.
이렇게 선언문이 코드의 가장 위쪽으로 끌어올려진 것처럼 동작하는 것을 호이스팅이라 한다.
var를 let으로 바꿔 실행할 경우 참조 에러가 뜨기 때문에 호이스팅이 되지 않는건가? 착각할 수 있는데,
let도 호이스팅이 되지만 선언만 될 뿐 초기화 단계를 거치지 않은 상태에서 실행되기 때문에
참조 에러가 뜨는 것이다.
할당, 재할당과 가비지 콜렉터
변수에 값을 할당한다는 것은 메모리의 특정 주소에 그 값을 기억하고, 식별자로 구분하도록 만드는 것이다.
var a = 10;의 경우 a에 undefined의 주소가 매칭 되었다가 다시 10의 주소로 변경되기 때문에
엄연히 말하자면 재할당이라고 볼 수 있다.
이렇게 값을 재할당할 때에는 메모리 셀 안의 값을 바꾸는 것이 아니라
다른 메모리 셀 안에 값을 기억하고 그 셀의 주소를 변수에 새로 알려주는 것이다.
그럼 이전 주소 안에 기억된 undefined는 어떻게 될까?
이 값은 어떤 식별자와도 연결되어 있지 않으며, 필요가 없어진다.
이러한 불필요한 값들을 가비지 콜렉터에 의해 메모리에서 자동으로 해제된다.
그러나 자바스크립트는 개발자가 직접적인 메모리 제어를 할 수 없으므로
가비지가 메모리에서 언제 해제될지는 알 수 없다.
식별자 네이밍 규칙
파이썬 식별자 네이밍 규칙과 비슷하다.
일단 예약어(자바스크립트에서 이미 사용되는 단어)를 사용할 수 없고,
숫자로 시작할 수 없고,
문자, 숫자, 언더바, $를 사용할 수 있다.
하이픈은 사용할 수 없다!
그리고 대소문자도 구별한다.
여러 단어로 이루어진 식별자는 카멜 케이스(camelCase)를 사용해 표기한다.
다음 포스트에선 자바스크립트의 데이터 타입에 대해 알아보자
'Programming > JavaScript' 카테고리의 다른 글
자바스크립트의 연산자 (0) | 2020.12.14 |
---|---|
자바스크립트의 데이터 타입과 동적 타이핑 (0) | 2020.12.13 |
자바스크립트(JavaScript)에 대해 가볍게 알아보자 (1) | 2020.12.11 |
댓글