자료형 — 값에도 종류가 있다
Article
변수라는 상자에 값을 담는 법을 배웠다. 이제 그 안에 들어가는 값에도 종류가 있다는 걸 볼 차례다.
숫자 3과 글자 "3"은 화면에는 비슷하게 보이지만 완전히 다른 값이다. 하나는 계산할 수 있고 하나는 이어붙일 수 있다. 이 구분이 자료형이다.
큰 틀부터
자바스크립트의 값은 크게 두 부류로 나뉜다. 이 구분은 이 시리즈 끝까지 계속 따라온다.
- 값
- 원시 타입
- number
- string
- boolean
- undefined
- null
- symbol
- bigint
- 객체 타입
- object
- array
- function
- 원시 타입
원시 타입은 일곱 개고, 나머지는 전부 객체다. 지금 다 외울 필요는 없다. 실제로 매일 쓰는 건 앞의 다섯 개다.
매일 쓰는 다섯 가지
number — 숫자
정수와 소수를 구분하지 않는다. 둘 다 number다.
const age = 27;
const height = 178.5;
const minus = -10;
특이한 값도 몇 개 있다.
console.log(1 / 0);
console.log("글자" * 2);
- Infinity
- NaN
Infinity는 무한대고, NaN은 "Not a Number", 숫자가 아니라는 뜻이다. 숫자로 계산할 수 없는 걸 계산하려 하면 나온다.
string — 문자열
따옴표로 감싼 글자다. 작은따옴표, 큰따옴표, 백틱 셋 다 된다.
const a = "큰따옴표";
const b = '작은따옴표';
const c = `백틱`;
셋의 기능은 거의 같지만, 백틱만 할 수 있는 게 있다. 변수를 문장 안에 끼워 넣는 것이다.
const name = "지원";
console.log("안녕, " + name + "님");
console.log(`안녕, ${name}님`);
- 안녕, 지원님
- 안녕, 지원님
아래쪽이 훨씬 읽기 좋다. 백틱으로 감싸고 ${ } 안에 값을 넣는 이 문법을 템플릿 리터럴이라 부른다. 앞으로 계속 쓴다.
boolean — 참과 거짓
값이 딱 두 개뿐이다. true와 false.
const isAdult = true;
const isMember = false;
console.log(10 > 5);
- true
비교의 결과가 boolean이다. 조건문에서 "이 길로 갈지 말지"를 정하는 데 쓰인다.
undefined 와 null — 둘 다 "없음"인데 왜 둘일까
초보자가 가장 자주 헷갈리는 지점이다. 결론부터 말하면 누가 비웠는지가 다르다.
undefined
자바스크립트가 비워둔 것
- 선언만 하고 값을 안 넣었을 때
- 없는 속성을 꺼냈을 때
- 함수가 아무것도 반환하지 않을 때
- "아직 값이 정해지지 않았다"
null
개발자가 일부러 비운 것
- 직접
null을 넣어야만 생긴다 - "여기 값이 없다"는 의도적 표시
- 찾는 걸 못 찾았을 때 반환값으로 쓴다
- "비어 있음을 알고 있다"
코드로 보면 차이가 분명하다.
let a;
console.log(a);
let b = null;
console.log(b);
const user = { name: "지원" };
console.log(user.age);
- undefined
- null
- undefined
a는 값을 넣지 않았으니 자바스크립트가 알아서 undefined를 넣어뒀다. b는 내가 직접 "비었다"고 표시했다. user.age는 존재하지 않는 속성이라 undefined가 나온다.
typeof — 타입을 확인하는 법
값의 타입이 궁금하면 typeof를 앞에 붙인다.
console.log(typeof 42);
console.log(typeof "글자");
console.log(typeof true);
console.log(typeof undefined);
console.log(typeof { name: "지원" });
console.log(typeof [1, 2, 3]);
console.log(typeof null);
- 'number'
- 'string'
- 'boolean'
- 'undefined'
- 'object'
- 'object'
- 'object'
마지막 두 줄이 이상하다.
배열이 'object'로 나오는 건 버그가 아니다. 배열은 실제로 객체의 한 종류다. 배열인지 확인하려면 전용 함수를 쓴다.
console.log(Array.isArray([1, 2, 3]));
console.log(Array.isArray({ a: 1 }));
- true
- false
원시 타입과 객체 타입의 진짜 차이
이제 3강 끝에서 미뤄뒀던 이야기를 마무리한다. 왜 const 배열에는 값을 추가할 수 있었나.
핵심은 상자에 무엇이 들어 있느냐다.
원시 타입은 값이 상자에 직접 들어간다. 객체는 너무 커서 상자에 안 들어가므로, 다른 곳에 두고 그 위치만 상자에 적어둔다.
원시 타입은 값 자체를, 객체 타입은 위치를 담는다
- age
- 27
- name
- "지원"
- scores
- 0x1a2b
- [90, 85, 100]
- user
- 0x3c4d
- { name: "지원" }
이 차이는 복사할 때 겉으로 드러난다.
let a = 10;
let b = a;
b = 20;
console.log(a);
let x = [1, 2];
let y = x;
y.push(3);
console.log(x);
- 10
- [1, 2, 3]
첫 번째는 예상대로다. b를 바꿔도 a는 그대로다. 값 자체가 복사됐기 때문이다.
두 번째가 함정이다. y를 바꿨는데 x도 바뀌었다. 복사된 건 배열이 아니라 위치였고, x와 y가 같은 배열을 가리키고 있었기 때문이다.
- 01
x 가 배열을 가리킨다
배열은 메모리 어딘가에 있고, x 에는 그 위치가 적힌다.
let x = [1, 2]; - 02
y 가 위치를 복사한다
배열이 복사된 게 아니다. 주소만 복사됐다. 이제 둘이 같은 배열을 본다.
let y = x; - 03
y 로 배열을 바꾼다
x 가 보고 있는 것도 같은 배열이므로 함께 바뀐 것처럼 보인다.
y.push(3); // x 도 [1, 2, 3] 이 된다
이 동작 때문에 생기는 버그가 아주 흔하다. 복사본을 진짜로 만들고 싶다면 별도의 방법이 필요한데, 18강에서 스프레드 문법과 함께 다룬다.
나머지 두 개는 가볍게
symbol과 bigint는 입문 단계에서 거의 만나지 않는다. 존재만 알아두면 된다.
| 타입 | 언제 쓰나 | 예시 |
|---|---|---|
| symbol | 절대 겹치지 않는 이름이 필요할 때 | Symbol("id") |
| bigint | number 로 감당 안 되는 큰 정수 | 9007199254740993n |
정리하면
- 원시 타입 일곱 개(
number,string,boolean,undefined,null,symbol,bigint)와 객체가 있다. undefined는 자바스크립트가 비워둔 것,null은 개발자가 일부러 비운 것이다.typeof null이'object'인 건 고칠 수 없는 옛날 버그다.- 원시 타입은 값이, 객체 타입은 주소가 복사된다. 이 하나만 기억해도 나중에 버그를 크게 줄인다.
다음 강의부터 Part 2로 넘어간다. 숫자와 문자열을 실제로 다루는 방법을 본다.