6장 데이터 타입
데이터 타입(줄여서 ‘타입’이라고도 한다)은 값의 종류를 말한다. 자바스크립트의 모든 값은 데이터 타입을 갖는다.
자바스크립트(ES6)는 7개의 데이터 타입을 제공한다. 7개의 타입은 원시 타입과 객체 타입으로 분류할 수 있다.
6.1 숫자 타입
C나 자바의 경우, 정수와 실수를 구분해서 int
, long
, float
, double
등과 같은 다양한 숫자 타입을 제공한다. 하지만 자바스크립트는 독특하게 하나의 숫자 타입만 존재한다.
ECMAScript 사양에 따르면 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따른다. 즉, 모든 수를 실수
로 처리하며, 정수만 표현하기 위한 데이터 타입이 별도로 존재하지 않는다.
// 모두 숫자 타입이다.
var integer = 10; // 정수
var double = 10.12; // 실수
var negative = -20; // 음의 정수
var binary = 0b01000001; // 2진수
var octal = 0o101; // 8진수
var hex = 0x41; // 16진수
// 표기법만 다를 뿐 모두 같은 값이다.
console.log(binary); // 65
console.log(octal); // 65
console.log(hex); // 65
console.log(binary === octal); // true
console.log(octal === hex); // true
숫자 타입은 추가적으로 세 가지 특별한 값도 표현할 수 있다.
Infinity
: 양의 무한대-Infinity
: 음의 무한대NaN
: 산술 연산 불가(not-a-number)
6.2 문자열 타입
문자열은 0개 이상의 16비트 유니코드 문자(UTF-16)의 집합으로 전 세계 대부분의 문자를 표현할 수 있다.
작은따옴표(''
), 큰따옴표(""
), 또는 백틱(
)으로 텍스트를 감싼다. 자바스크립트에서 가장 일반적인 표기법은 작은따옴표를 사용하는 것이다.
6.3 템플릿 리터럴
템플릿 리터럴은 멀티라인 문자열, 표현식 삽입, 태그드 템플릿 등 편리한 문자열 처리 기능을 제공한다. 템플릿 리터럴은 런타임에 일반 문자열로 변환되어 처리된다.
6.4 불리언 타입
참, 거짓을 나타내는 true
와 false
뿐이다.
6.5 undefined 타입
undefined
타입의 값은 undefined
가 유일하다.
var
키워드로 선언한 변수는 암묵적으로 undefined
로 초기화된다. 따라서 변수를 선언한 이후 값을 할당하지 않은 변수를 참조하면 undefined
가 반환된다.
var foo;
console.log(foo); // undefined
변수를 참조했을 때 undefined
가 반환된다면 참조한 변수가 선언 이후 값이 할당된 적이 없는, 즉 초기화되지 않은 변수라는 것을 간파할 수 있다.
undefined
를 개발자가 의도적으로 변수에 할당한다면 undefined
의 본래 취지와 어긋날뿐더러 혼란을 줄 수 있으므로 권장하지 않는다.
변수에 값이 없다는 것을 명시할 때는 null
을 할당한다.
6.6 null 타입
null
타입의 값이 null
이 유일하다. 대소문자를 구별하므로 null
은 Null, NULL 등과 다르다.
변수에 null
을 할당하는 것은 변수가 이전에 참조하던 값을 더 이상 참조하기 않겠다는 의미다. 이전에 할당되어 있던 값에 대한 참조를 명시적으로 제거하는 것을 의미하며, 자바스크립트 엔진은 누구도 참조하지 않는 메모리 공간에 대해 가비지 콜렉션을 수행할 것이다.
6.7 심벌 타입
심벌은 ES6에서 추가된 7번째 타입으로, 변경 불가능한 원시타입의 값이다. 심벌 값은 다른 값과 중복되지 않는 유일무이한 값이다. 따라서 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.
심벌 의외의 원시 값은 리터럴을 통해 생성하지만 심벌은 Symbol
함수를 호출해 생성한다. 이때 생성된 심벌 값은 외부에 노출되지 않으며, 다른 값과 절대 중복되지 않는 유일무이한 값이다.
// 심벌 값 생성
var key = Symbol('key');
console.log(typeof key); // symbol
// 객체 생성
var obj = {};
// 이름이 충돌할 위험이 없는 유일무이한 값인 심벌을 프로퍼티 키로 사용한다.
obj[key] = 'value';
console.log(obj[key]); // value
6.8 객체 타입
자바스크립트의 데이터 타입은 크게 원시 타입
과 객체 타입
으로 분류한다고 했다. 원시 타입과 객체 타입은 근본적으로 다르다는 의미일 것이다. 이에 대해서는 아직 객체에 대해 살펴보지 않았으므로 11장 “원시 값과 객체의 비교”에서 자세히 살펴본다.
중요한 것은 자바스크립트는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체라는 것이다. 지금까지 살펴본 6가지 타입 이외의 값은 모두 객체 타입이다.
6.9 데이터 타입의 필요성
6.9.1 데이터 타입에 의한 메모리 공간의 확보와 참조
값은 메모리에 저장하고 참조할 수 있어야 한다. 메모리에 값을 저장하려면 먼저 확보해야 할 메모리 공간의 크기를 알아야 한다. 다시 말해, 몇 바이트의 메모리 공간을 사용해야 낭비와 손실 없이 값을 저장할 수 있는지 알아야 한다.
var score = 100;
자바스크립트 엔진은 리터럴 100을 숫자 타입의 값으로 해석하고 숫자 타입의 값 100을 저장하기 위해 8바이트의 메모리 공간을 확보한다. 그리고 100을 2진수로 저장한다.
자바스크립트는 숫자 타입의 값을 생성할 때 배정밀도 64비트 부동소수점 형식을 사용한다.
값을 참조하는 경우를 생각해보자. 식별자 score
를 통해 숫자 타입의 값 100이 저장되어 있는 메모리 공간에 주소를 찾아갈 수 있다. 정확히 말하면 숫자 값 100이 저장되어 있는 메모리 공간의 선두 메모레 셀의 주소를 찾아갈 수 있다.
6.9.2 데이터 타입에 의한 값의 해석
모든 값은 데이터 타입을 가지며, 메모리에 2진수, 즉 비트의 나열로 저장된다. 메모리에 저장된 값은 데이터 타입에 따라 다르게 해석될 수 있다.
데이터 타입이 필요한 이유는 다음과 같다.
- 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해
- 값을 참조할 때 한 번에 읽어 들어야 할 메모리 공간의 크기를 결정하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
6.10 동적 타이핑
6.10.1 동적 타입 언어와 정적 타입 언어
정적 타입
언어는 변수의 타입을 변경할 수 없으며, 변수에 선언한 타입에 맞는 값만 할당할 수 있다.
자바스크립트는 정적 타입 언어와 다르게 변수를 선언할 때 타입을 선언하지 않는다.
typeof
연산자를 변수를 연산하면 변수의 데이터 타입을 반환한다. 정확히 말하면 변수의 데이터 타입을 반환하는 것이 아니라 변수에 할당된 값의 데이터 타입을 반환하는 것이다.
자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정(타입 추론)된다. 그리고 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다. 이러한 특징을 동적 타이핑이라고 하며, 자바스크립트를 정적 타입 언와 구별하기 위해 동적 타입 언어라 한다.
6.10.2 동적 타입 언어와 변수
변수를 사용할 때 주의사항은 다음과 같다.
- 변수는 꼭 필요한 경우에 한해 제한적으로 사용한다.
- 변수의 유효 범위(스코프)는 최대한 좁게 만들어 변수으 부작용을 억제해야 한다.
- 전역 변수는 최대한 사용하지 않도록 한다.
- 변수보다는 상수를 사용해 값의 변경을 억제한다.
- 변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍 한다.
코드는 오해하지 않도록 작성해야 한다. 오해는 커뮤니케이션을 어렵게 하고 생산성을 떨어뜨리는 것은 물론 팀의 사기까지 저하시킨다. 코드는 동작하는 것만이 존재 목적은 아니다. 사람이 이해할 수 있는 코드, 즉 가독성이 좋은 코드가 좋은 코드다.