데이터 타입과 변수
변수는 값의 위치를 기억하는 저장소이다. 이는 즉, 메모리 상의 주소를 의미한다. 값을 저장한 메모리 주소에 접근하기 위해 사람이 이해할 수 있는 언어로 지정한 식별자를 말한다.
메모리에 값을 저장하는 순서
- 메모리 공간을 확보해야한다.
- 메모리의 크기를 알아야한다.
- 이는 값의 종류(데이터 타입)에 따라 메모리의 크기가 다를 것이다.
C언어를 예로 들었을 때, 4byte 정수형인 int형 변수 선언을 만나면, 시스템은 이후에 할당될 값과는 상관없이 4byte의 메모리 영역을 확보한다. 그리고 이 int형 변수에 값을 할당할 때에는 int형 값을 할당해야 한다.
반면, 자바스크립트는 동적 타입 언어라서, 변수의 타입 지정 없이 값이 할당되는 과정에서 자동으로 변수의 데이터 타입이 결정된다. 즉, 변수는 고정된 타입이 없고, 같은 변수에 여러 타입의 값을 할당할 수 있다.
데이터 타입
데이터 타입이란, 프로그래밍 언어에서 사용할 수 있는 데이터 종류를 말한다. 모든 데이터는 메모리에 저장하고 참조할 수 있어야 한다.
자바스크립트는 ES6에 따라서 7개의 데이터 타입을 제공한다.
원시 타입
- boolean
- null
- undefined
- number
- string
- symbol
객체 타입
- object
자바스크립트의 데이터 타입은 원시 타입과 객체 타입으로 나눌 수 있다.
원시 타입
원시 타입은 변경 불가능한 값(immutable value)
이며, pass-by-value(값에 의한 전달)이다.
- number
자바스크립트는 float, int, long 등의 다양한 number 타입이 없다. 숫자 타입은 number 하나만 존재한다. 모든 수를 실수로 처리한다. 정수만을 표현하기 위한 데이터 타입은 없다.
2, 8, 16진수 데이터 타입 또한 제공하지 않기 때문에 이들 값을 참조하면 모두 10진수로 해석된다.
Infinity
: 양의 무한대-Infinity
: 음의 무한대NaN
: 산술 연산 불가(not a number)
- string
문자열 타입은 텍스트 데이터를 나타내는 데에 사용한다. 자바스크립트의 문자열은 원시 타입이며 변경 불가능하다. 즉, 한 번 생성하면 그 후엔 변경할 수 없음을 의미한다.
문자열은 배열처럼 인덱스를 통해 접근할 수 있는데, 이와 같은 특성을 갖는 데이터를 유사 배열
이라고 한다.
위처럼 이미 생성된 문자열의 일부를 변경해도 반영되지 않는다. 에러는 발생하지 않는다. 한 번 생성된 문자열은 read only로 변경할 수 없다. 재할당하 것은 가능하다. 이는 해당 문자열의 주소를 가리키고 있던 식별자가 다른 새로운 문자열을 가리키도록 변경해주기 때문이다.
- boolean
boolean 타입의 값은 논리적 참, 거짓을 나타내는 true
와 false
를 의미한다.
비어있는 문자열과 null, undefined, 숫자 0
은 false로 간주된다.
- undefined
선언 이후 값을 할당하지 않은 변수는 undefined
를 가진다.
변수 선언에 의해 확보된 메모리 공간을 처음 할당이 이루어질 때까지 빈 상태로 내버려두지 않고, 자바스크립트 엔진이 undefined
로 초기화하기 때문이다.
개발자가 의도적으로 undefined
를 할당하는 경우?
- null
null
은 의도적으로 변수에 값이 없다는 것을 명시할 때 사용한다.
변수가 기억하는 메모리 주소의 참조 정보(할당되어 있던 값)를 제거하거나, 명시적으로 빈 값이라는 것을 알릴 때 사용한다.
typeof
연산자로 null체크를 하면 안되고 일치 연산자(===)를 사용하여야 한다.
참고: https://github.com/FEDevelopers/tech.description/wiki/%E2%80%9Ctypeof-null%E2%80%9D%EC%9D%98-%EC%97%AD%EC%82%AC
- symbol
symbol은 ES6에서 새롭게 추가된 데이터 타입으로 변경 불가능한 원시 타입의 값이다. (아직 써본적 없음..) 심볼은 이름의 충돌 위험이 없는 유일한 객체의 프로퍼티 키를 만들기 위해 사용한다.
참고: https://medium.com/@hyunwoojo/javascript-symbol-%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-6aa5903fb6f1
객체 타입
객체는 데이터와 그 데이터에 관련한 동작을 모두 포함할 수 있는 개념적 존재이다. 즉, 프로퍼티와 메소드를 포함할 수 있는 독립적 주체이다.
자바스크립트는 원시 타입을 제외한 나머지 값들은 모두 객체이다. 객체는 pass-by-reference(참조에 의한 전달)
방식으로 전달된다.
참고: https://penguin2ip.tistory.com/9
변수
변수는 프로그램에서 사용되는 데이터를 필요한 때에 재사용하기 위해 식별자를 명시한 것이다. 이 고유한 식별자를 변수명이라 하고, 참조할 수 있는 데이터 값을 변수값이라 한다.
- 변수는
var, let, const
키워드를 사용하여 선언한다. - 할당 연산자를 사용하여 값을 할당한다.
- 식별자인 변수명을 사용해 변수에 저장된 값을 참조한다.
메모리에 저장된 데이터를 참조하려면 데이터가 저장된 메모리상의 주소를 알아야하는데, 여기서 식별자는 데이터가 저장된 메모리 주소를 기억한다. 즉, 식별자를 통해 메모리에 저장된 값을 참조할 수 있다. 변수명은 또한 데이터의 의미를 정확히 할 수 있어 코드 가독성이 좋아지는 효과도 있다.
변수의 선언
재사용성을 생각하여 변수에 저장해서 그 값을 캐싱하여 사용하도록 한다. 변수를 선언할 때는 특수문자를 제외한 영문자나 underscore, 또는 달러 기호로 시작하여야 한다. 이어지는 문자에는 숫자도 사용이 가능하다. 자바스크립트는 대소문자를 구별한다.
값을 할당하지 않은 변수는 undefined
로 초기값을 갖는다. 선언하지 않은 변수에 접근하면 ReferenceError
가 발생한다.
변수는 중복 선언이 가능하다. 하지만 비추..의도치 않게 변수의 값을 변경하는 부작용이 있을 수 있기 때문이다.
암묵적 전역 변수
변수 선언시 var
키워드를 생략할 수 있는데, 이 변수는 전역 변수가 된다.
이것도 비추비추! 의도하지 않게 변수를 전역화할 수 있기 때문이다.
동적 타이핑
자바스크립트는 동적 타입 언어이다. 변수 타입 지정을 미리 하지 않고 할당되는 과정에서 값의 타입에 의해 자동으로 타입이 결정된다는 의미이다.
즉, 같은 변수에 여러 타입의 값을 할당할 수 있다. 이를 동적 타이핑이라 한다.
변수 호이스팅
var
키워드를 사용하여 변수를 선언, 할당할 경우, 위 변수 foo는 아직 선언되지 않았으므로 ReferenceError
가 발생할 것 같지만 undefined
가 출력된다.
이는 자바스크립트의 특징으로 모든 선언문은 호이스팅되기 때문이다.
호이스팅이란, var, function 선언문 등의 모든 선언문이 해당 스코프의 선두로 끌어올려져 동작하는 것을 말한다.
새롭게 알게된 사실
let, const
가 호이스팅이 되지 않는 것이 절대 아니다. let, const도 호이스팅이 된다. 다만, 선언문에 도달할 때까지 엑세스하지 못할 뿐이다!!!!!
호이스팅 참고: https://medium.com/korbit-engineering/let%EA%B3%BC-const%EB%8A%94-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EB%90%A0%EA%B9%8C-72fcf2fac365
-
선언 단계 변수 객체에 변수를 등록한다. 이 변수 객체가 스코프가 참조하는 대상이 된다.
-
초기화 단계 변수 객체에 등록된 변수를 메모리에 할당한다. 여기서 변수는 undefined로 초기화된다.
-
할당 단계 undefined로 초기화된 변수에 실제값을 할당한다.
var
키워드로 선언된 변수는 선언 단계와 초기화 단계가 한꺼번에 이루어진다. 그래서 변수 선언문 이전에 변수에 접근하여도 변수 객체에 변수가 존재하기 때문에 에러가 발생하지 않는다.
자바스크립트의 변수는 블록 레벨 스코프를 가지지 않고, 함수 레벨 스코프를 가진다.
ES6에서 도입된 let, const
키워드를 사용하면 블록 레벨 스코프를 사용할 수 있다.
함수 레벨 스코프
함수 내에서 선언된 변수는 함수 내에서만 유효하다. 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이고, 외부에서 선언한 변수는 전역 변수이다.
블록 레벨 스코프
코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하고, 코드 블록 외부에서는 참조할 수 없다.
따라서 위 그림에서 블록 내부의 foo는 전역 변수이므로 foo의 값이 바뀌게된다.