해당 시리즈는 Leonardomso의 33 Concepts Every JavaScript Developer Should Know 를 보고 공부, 정리한 시리즈이며, 자세한 내용은 링크를 확인하길 바란다.
자바스크립트(ES11)에서 제공하는 8개의 데이터 타입에 대해서 알아보자
(이번 장에서는 타입들의 종류와 특징에 대해서만 알아보고자 한다.
원시타입과 참조타입의 할당과 관련된 부분은 다음 장에서 다룰 것이다.)
자바스크립트에서 제공하는 데이터 타입은 크게 원시 타입(Primitive Type
) 과 객체 타입(Object/Reference Type
) 으로 나눌 수 있다.
아래 도표와 같은 원시 타입은 총 7개의 세부 타입으로 나눌 수 있다.
자바스크립트 언어는 동적 타입 언어이기에 갖는 가장 큰 특징
언어에 따라 변수가 데이터 타입을 가지는 방식 2가지로 분류할 수 있다.
let
, const
) 만 사용해서 선언한다.동적 타이핑 : 변수는 선언이 아닌 할당에 의해서 타입이 결정되며, 재할당을 통해 언제든 변수의 타입이 동적으로 바뀔 수 있다.
다시 정리하자면 아래와 같다.
동적 언어는 타입이 언제든 바뀔 수 있기에, 프로그램이 복잡해지면 변수의 값을 추적하는데 어려움이 있으며, 오류를 발생할 가능성이 정적 타입 언어보다 높다.
또한, 동적이기에 해당 변수를 출력해보기 전까지 변수의 타입에 대해 확신할 수 없다.
그렇기에 다음과 같은 주의 사항은 항상 유념하자.
const
)를 사용해 값의 변경을 억제한다.값의 종류에 따라 정해진 크기의 메모리 공간을 확보하고, 한번에 읽어들일 메모리의 크기를 파악
값은 메모리에 저장되고 참조할 수 있어야 한다.
저장하기에 앞서 먼저 확보해야되는 메모리의 양을 파악해야 하며, 어느 정도의 공간이 있어야 메모리의 낭비나 값의 손실없이 저장할 수 있는지 알아야 한다.
자바스크립트에서는 데이터 타입을 통해 값의 종류에 따라 정해진 크기의 메모리 공간을 확보한다.
또한, 읽어들일 때도 데이터 타입을 통해 한번에 읽어들일 메모리의 크기를 파악한다.
var number = 10
메모리에 있는 2진수를 어떻게 해석할지 결정
값이 메모리에 저장될 때 2진수, 즉 비트의 나열로 저장된다.
이 때, 해당하는 비트를 데이터 타입에 따라 다르게 해석할 수 있다.
0100 0001
을 숫자로 해석하면 65 이지만, 문자로 해석하면 A 이다.
그렇기에 데이터 타입은 메모리에 있는 2진수를 어떻게 해석할지 결정해준다.
객체를 제외한 모든 타입의 불변 값을 정의
정수, 실수를 모두 포함한 자바스크립트의 숫자 형식
배정밀도 64비트 부동소수점 형식을 따른다.
자바스크립트가 부동소수점 형식을 따르기에, 아래와 같은 결과를 얻는다.
console.log(0.1+0.2) // 0.30000000000000004
console.log(0.1+0.2 === 0.3) // false
그렇기에 소수점 계산을 할 때, Math.round
를 사용하는 방식 등을 활용하여 주의하자!
모든 수를 실수로 표현한다.
즉, 정수만 표현하는 별도의 타입이 존재하지 않는다.
console.log(1 === 1.0) // true
console.log(4 / 2) // 2
console.log(3 / 2) // 1.5
Infinity
: 양의 무한대
-Infinity
: 음의 무한대
NaN
: 산술 연산 불가 Not-a-Number
자바스크립트는 대소문자를 구별하기에 NaN
을 NAN, nan, Nan 과 같이 표현하면 발생한다! (값이 아닌 식별자로 판단)
var x = nan // ReferenceError: nan is not defined
자바스크립트의 덱스트 데이터를 나타낸다.
16비트 유니코드 문자의 집합(UTF-16)으로 전세계 대부분의 문자를 표현한다.
작은따옴표(''
), 큰따옴표(""
), 백틱(``) 으로 텍스트를 감싸서 표현한다.
''
)를 사용하는 것.만약 위 방식대로 감싸지 않는다면, 자바스크립트 엔진은 키워드나 식별자로 인식
var string = 'hello'
var string = hello // ReferenceError: hello is not defined
C 나 자바와 다르게 JS에서는 배열, 객체가 아닌 원시 타입이자 불변하는 값으로 문자열을 표현한다.
ES6부터 도입된 새로우면서, 편리한 문자열 처리를 돕는 문자열 표기법
일반 문자열 사용
일반 문자열에서는 줄바꿈(개행)이 허용되지 않는다.
var str = 'Hello
world'
// SyntaxError: Invalid or unexpected token
그래서 일반 문자열 안에서 개행 처리를 하려면 이스케이프 시퀸스를 사용한다. (다양한 이스케이프 시퀸스는 여기를 클릭해서 알아보자!)
var str = 'Hello\nworld'
console.log(str)
// Hello
// world
템플릿 리터럴 사용
템플릿 리터럴에서는 이스케이프 시퀀스를 사용하지 않고 줄바꿈이 허용된다.
var str = `Hello
world`
console.log(str)
// Hello
// world
일반 문자열 사용
일반 문자열에서는 +
연산자를 사용해, 문자열들을 연결할 수 있다.
var count = 'three'
var pet = 'dog'
console.log('There are ' + count + ' ' + pet + 's ' + 'walking.')
// There are three dogs walking.
템플릿 리터럴 사용
표현식 삽입을 통해서 매우 간단하게 표현할 수 있다.
var count = 'three'
var pet = 'dog'
console.log(`There are ${count} ${pet}s walking.`)
// There are three dogs walking.
console.log(`${1 + 2}`) // 3
위처럼 백틱으로 감싸고 삽입하려는 표현식을 ${ }
로 감싸면 된다.
논리의 참, 거짓
true
와 false
뿐이다.
앞서 말한 것처럼, 대소문자를 구분하기에 반드시 모두 소문자로 true
, false
로 작성해야 한다!
(참고로 파이썬에서는 True, False 처럼 앞글자만 대문자다.)
console.log(True) // ReferenceError: True is not defined
console.log(tue) // true
변수를 초기화 할 때 사용되는 값
undefined
가 유일하다.
자바스크립트에서 변수 선언 후, 값이 할당되지 않는다면, 엔진이 자동적으로 undefined
로 초기화한다.
var hi
console.log(hi) // undefined
이는 개발자가 의도적으로 할당하는 값이 아닌 엔진이 변수를 초기화할 때 사용하는 값이기에, undefined
를 반환한다면 초기화되지 않는 변수임을 유추할 수 있다.
개발자가 의도적으로 undefined
를 변수에 할당하는 것을 권장하지 않으며, 이 때는 다음에 나올 null
을 사용하자!
변수에 값이 없다는 것을 명시하는 값
null
이 유일하며, 대소문자를 명확히 구분해야 한다.
변수에 값이 없다는 것을 의도적으로 명시하기 위해 사용하며, 만약 null
을 할당하면, 더이상 해당 이전 참조 값을 참조하지 않겠다는 의미이다.
함수가 유효한 값을 반환할 수 없는 경우, 명시적으로 null
을 반환하기도 한다.
<!DOCTYPE html>
<html>
<body>
<script>
var element = document.querySelector('.myClass')
console.log(element) // null
// HTML 문서에 myClass 클래스를 갖는 요소가 없기에 null을 반환한다!
</script>
</body>
</html>
ES6에서 추가된 7번째 타입, 중복되지 않은 유일무이한 값
주로 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.
앞선 원시 타입들은 리터럴을 통해서 생성하지만, 심볼 타입은 Symbol
함수를 호출해서 생성한다.
const mySymbol = Symbol()
console.log(typeof mySymbol) // symbol
new
연산자를 함께 호출하지 않는다.선택적으로 문자열을 인수로 전달할 수 있다.
하지만, 이 때 전달되는 문자열은 심볼에 대한 설명을 위한 용도일 뿐 심볼 값 생성에 어떤 영향도 주지 않는다.
즉, 다른 심볼에 같은 문자열을 전달한다고 하러다로 서로 다르다. ( 심볼은 유일무이하기 때문! )
const mySymbol1 = Symbol('hello')
const mySymbol2 = Symbol('hello')
console.log(mySymbol1 === mySymbol2) // false
암묵적으로 불리언 타입으로 변환은 되나, 숫자나 문자열 타입으로 변환은 안된다.
ES11(2020)에서 추가된 8번째 타입, Number 타입보다 큰 수를 표현하는 값
정수 끝에 n
을 추가하여 표현한다.
기존에 Number 타입이 갖고 있는 안전 최대 정수값(2^53 - 1
) 를 넘는 숫자에 대한 계산이 가능하다.
const x = Number.MAX_SAFE_INTEGER + 1
const y = Number.MAX_SAFE_INTEGER + 2
// 기존 Number에서는 안전 최대 정수값를 넘어간 계산은 올바르게 비교하지 못한다.
console.log(x === y) // true
const xn = 2n ** 53n // 9007199254740992n
const yn = x + 1n //9007199254740993n
// BigInt를 활용하면 안전 최대 정수값을 넘어간 계산도 올바르게 비교한다.
console.log(x === y) // false
단, BigInt는 Number 타입과 혼합해 연산할 수 없다.
const xn = 2n ** 53n
console.log(xn + 1) // TypeError: Cannot mix BigInt and other types, use explicit conversions
자바스크립트의 데이터 타입의 큰 분류 중 하나이자, 자바스크립트를 구성하는 핵심 개념
객체 타입은 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조이다.
객체는 변경 가능한 값이다.
객체는 0개 이상의 프로퍼티로 구성된 집합이며, 프로퍼티는 키 key 와 값 value 로 구성된다.
객체를 생성할 수 있는 방법은 여러가지가 있지만, 대개 객체 리터럴을 많이 사용한다.
var myself = {
name: 'Park',
age: 99,
hi: function () {
console.log('Hi!')
}
}
var empty = {} // 빈 객체
객체는 프로퍼티의 집합이며, 프로퍼티는 키와 값으로 구성된다.
var myself = {
name: 'Park',
age: 99,
}
,
쉼표로 구분한다. (마지막에 쉼표로 써도 안써도 무방하다.)객체에 묶여 있는 함수
var basic = {
x: 3,
pow: function () { // 제곱을 하는 메서드
return this.x ** 2 // this 는 basic 을 가리킨다.
}
}
console.log(basic.pow()) // 9
크게 2가지 방법이 존재한다.
var myself = {
name: 'Park',
age: 99,
}
// 마침표 표기법
console.log(myself.name) // Park
// 대괄호 표기법
console.log(myself['name']) // Park
대괄호 표기법을 사용하여 프로미터에 접근할 때, 프로미터 키는 무조건 따옴표로 감싸야 한다.
console.log(myself[name]) // undefined
객체에 존재하지 않는 프로퍼티에 접근하면 undefined
를 반환한다. 단, 에러는 발생하지 않는다.
console.log(myself.skills) // undefined
var myself = {
name: 'Park'
}
// 갱신
myself.name = 'choi'
console.log(myself) // {name: 'choi'}
// 동적 생성
myself.age = 100
console.log(myself) // {name: 'choi', age: 100}
// 삭제
delete myself.age
console.log(myself) // {name: 'choi'}
삭제 시 delete
연산자를 사용한다.
만약, 존재하지 않는 프로퍼티를 삭제하려고 하면, 에러 없이 무시된다.
delete myself.skills
console.log(myself) // {name: 'choi'}
ES6에서 추가된 간편한 객체 리터럴의 확장 기능
프로퍼티 값에 사용될 변수명과 프로퍼티 키 이름과 동일하다면, 프로퍼티 키를 생략할 수 있으며, 키는 자동 생성된다.
let a = 1, b = 2
const obj = { a, b }
console.log(obj) // {a: 1, b: 2}
표현식을 통해 프로퍼티 키를 동적으로 생성할 수 있다.
단, 대괄호 표기법에서만 가능하다.
var egg = 'egg'
var i = 1
var nest = {}
nest[egg + '-' + i++] = i
nest[egg + '-' + i++] = i
nest[egg + '-' + i++] = i
console.log(nest) // {egg-1: 2, egg-2: 3, egg-3: 4}
메서드를 정의할 때 function 키워드를 생략한 축약 표현을 쓸 수 있다.
var basic = {
x: 3,
pow() { // 제곱을 하는 메서드
return this.x ** 2
}
}
console.log(basic.pow()) // 9
데이터 타입은 메모리 공간을 확보하고 읽어들일 크기를 파악하기 위해, 그리고 해당 메모리의 값을 해석하기 위해 필요하다. 자바스크립트는 7개의 원시타입과 1개의 객체타입을 갖으며, 동적 타입 언어이기에, 값이 타입을 갖으며 변수는 동적으로 변한다.
모던 자바스크립트 Deep Dive