해당 포스트는 자바스크립트 완벽 가이드라는 교재로 스터디를 하면서 11장을 정리한 포스트입니다.
주관적으로 해석한 내용이 들어가 있어서 잘못된 내용이 포함될 수 있습니다.
또한 교재의 모든 내용을 정리하지 않고 주관적인 판단에 의해 필요한 내용만 작성했습니다.
🗃️ Map과 Set
JavaScript
의 객체의 key
는 string
or symbol
이어야 하는 제약이 있어 ES6
에 추가된 스펙입니다.
0️⃣ Set
배열과 같은 값의 집합입니다.
- 특징
- 중복을 허용하지 않음
- 순서가 없어서 인덱스가 존재하지 않음 ( 하지만 순서는 기억하고 있음 )
- 이터러블하고 이터러블을 인자로 받음
size
,add()
,delete()
,clear()
,has()
,forEach()
- 요소를 검사할 때는 엄격하게 검사함 (
===
처럼 검사 ) - 요소 검사는 속도가 매우 빠름 (
has()
)
1
2
3
4
5
6
7
new Set("apple") // Set(4) {'a', 'p', 'l', 'e'}
const s = new Set();
s.add({a: 10}); // Set(1) {{…}}
s.add({a: 10}); // Set(2) {{…}, {…}}
s.has({a: 10}); // false
1️⃣ Map
배열과 같은 값의 집합이지만, 다른 데이터 타입으로 key
를 사용할 수 있습니다.
- 특징
- 인자는
[key, value]
형태 혹은[key, value]
의 이터러블로 받음 - 각
key
와value
가 연결된 것일 뿐 집합이 아님 size
,get()
,set()
,has()
,delete()
,clear()
,forEach()
,keys()
,values()
,entries()
- 인자는
1
2
3
4
const person = { name: "Aatrox", age: 26 };
const m1 = new Map([ [true, 1], /* ... [key, value] */ ]);
const m2 = new Map(Object.entries(person));
2️⃣ WeakSet
메모리 누수를 방지하는 Set
입니다.
- 특징
- 객체 타입을 요소로 받음 ( 가비지 컬렉터의 대상이 되는 값 )
add()
,has()
,delete()
메서드만 존재- 요소의 길이가 가변적이기 때문에
size
가 없음
요소가 약하게 참조되고 WeakMap
에서 참조한다고 하더라도 가비지 컬렉터에 의해 제거될 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
let o1 = { "1": 1 };
let o2 = { "2": 2 };
let o3 = { "3": 3 };
const ws = new WeakSet([o1, o2, o3]);
console.log(ws); // WeakSet {{…}, {…}, {…}}
o1 = null; // 키의 참조가 끊김
// "ws"에서 "o1"을 참조한다고 해도 가비지 컬렉터는 무시하고 "o1"을 할당 해제함
console.log(ws); // WeakSet {{…}, {…}}
3️⃣ WeakMap
메모리 누수를 방지하는 Map
입니다.
- 특징
key
는 반드시 객체나 배열같은 객체 타입이어야 함 ( 가비지 컬렉터의 대상이 되는 값 )get()
,set()
,has()
,delete()
메서드만 존재- 이터러블이 아님
- 요소의 길이가 가변적이기 때문에
size
가 없음
key
가 약하게 참조되고 WeakMap
에서 key
로 참조한다고 하더라도 가비지 컬렉터에 의해 제거될 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
let o1 = { "1": 1 };
let o2 = { "2": 2 };
let o3 = { "3": 3 };
const wm = new WeakMap([[o1, 1], [o2, 2], [o3, 3]]);
console.log(wm); // WeakMap {{…} => 1, {…} => 3, {…} => 2}
o1 = null; // 키의 참조가 끊김
// "wm"에서 "key"로 "o1"을 참조한다고 해도 가비지 컬렉터는 무시하고 "o1"을 할당 해제함
console.log(wm); // WeakMap {{…} => 3, {…} => 2}
❌ 형식화 배열과 이진 데이터
TODO: 나중에 필요해서 사용해보고 나서 작성
❌ 정규 표현식
정규 표현식은 내용이 방대하고 따로 구분하고 싶어서 다른 포스트에 작성했습니다.
⏱️ 날짜와 시간
0️⃣ Date 생성자
현재 동작하는 시스템의 시간을 기준으로 계산합니다.
- 인자
- 인자로 숫자를 받으면 1970년 1월 1일 이후 지난 시간을 나타내는 숫자로 간주함
- 년, 월, 일, 시, 분, 초, 밀리초 형태로 값을 받을 수 있음 ( 월은
0
부터 시작 )
1
2
new Date(0); // Thu Jan 01 1970 09:00:00 GMT+0900 (한국 표준시)
new Date(1970, 0, 1, 0, 0, 0, 0); // Thu Jan 01 1970 09:00:00 GMT+0900 (한국 표준시)
세계 협정 시간으로 계산하고 싶다면 Date.UTC()
를 사용하면 됩니다. ( 한국 기준 -8시간 )
1️⃣ 시간 가져오기 및 수정하기
getFull<>
, getUTCFull<>
, setFull<>
, setUTCFull<>
등을 사용할 수 있습니다.
<>
에는 Years
, Month
, Date
등이 사용될 수 있습니다.
1
2
3
4
5
6
7
8
9
10
const date = new Date(2023, 2, 21, 4, 30, 15); // Tue Mar 21 2023 04:30:15 GMT+0900 (한국 표준시)
date.getHours(); // 4
date.getUTCHours(); // 19 ( -8시간 )
date.getDate(); // 21
date.getUTCDate(); // 20 ( -8시간 )
date.setMinutes(10); // 1679339415000
console.log(date); // Tue Mar 21 2023 04:10:15 GMT+0900 (한국 표준시)
2️⃣ 타임스탬프
1970년 1월 1일 이후로 지난 시간을 밀리초 단위로 표시하는 것을 타임스탬프라고 합니다.
1
2
3
4
5
6
const date = new Date(0); // Thu Jan 01 1970 09:00:00 GMT+0900 (한국 표준시)
// 70초 더하기
date.setTime(date.getTime() + 70 * 1000); // 70000
console.log(date); // Thu Jan 01 1970 09:01:10 GMT+0900 (한국 표준시)
3️⃣ 날짜 연산
Date.valueOf()
는 타임스탬프를 반환하기 때문에 Date
객체는 비교 연산자로 비교할 수 있습니다.
1
2
3
4
5
6
7
const date1 = new Date(0); // Thu Jan 01 1970 09:00:00 GMT+0900 (한국 표준시)
const date2 = new Date(1000); // Thu Jan 01 1970 09:00:01 GMT+0900 (한국 표준시)
date1.valueOf(); // 0
date2.valueOf(); // 1000
date1 < date2; // true
날짜 연산에 오버플로가 발생하는 경우에는 setYear()
, setMonth()
, setDate()
등을 이용하는 것이 좋습니다.
( 오버플로우란 년/월/일/시/분/초가 다음으로 넘어가거나 이전으로 내려가는 경우를 의미 )
4️⃣ Date.parse()
문자열을 인자로 받아 날짜와 시간을 분석후 타임스탬프로 반환하는 정적 메서드입니다.
1
2
Date.parse("Thu Jan 01 1970 09:00:00 GMT+0900 (한국 표준시)"); // 0
Date.parse("Thu Jan 01 1970 09:01:00 GMT+0900 (한국 표준시)"); // 60000
🚫 Error 클래스
JavaScript
에서는 Error
클래스를 이용해서 에러를 발생시키는 것이 좋습니다.
Error
객체를 사용하면 JavaScript
의 스택이 캡쳐되기 때문에 디버깅할 때 도움이 되기 때문입니다.
1
2
3
4
5
try {
throw new Error("내가 만든 에러");
} catch (error) {
console.error(error); // Error: 내가 만든 에러 ( 하단에 캡쳐된 스택 출력됨 )
}
EvelError
, RangeError
, ReferenceError
, SyntaxError
, TypeError
, URIError
, HTTPError
등의 많은 서브 클래스가 있기 때문에 상황에 맞게 필요한 서브 클래스를 사용하면 됩니다.
🏭 JSON 직렬화와 분석
데이터 구조를 바이트나 문자 스트림으로 변경하는 것을 직렬화라고 합니다.
JSON.stringify()
와 JSON.parse()
를 이용해서 직렬화/역직렬화를 할 수 있습니다.
구체적인 사용법은 자바스크립트 완벽 가이드 6장에서 정리한 내용을 참고해주세요!
0️⃣ Date 형식 직렬화 및 역직렬화
주의할 점은 Date
객체 같은 경우 직렬화 하면 toJSON()
을 통해서 toISOString()
을 호출한 형태로 직렬화됩니다.
하지만 역직렬화를 하는 경우에는 ISO
에서 Date
형식으로 바꿔주지 않기 때문에 구체적인 설정이 필요합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const person = {
name: "Aatrox",
birth: new Date(0),
};
console.log(person.birth.toISOString()); // 1970-01-01T00:00:00.000Z
console.log(person.birth.toJSON()); // 1970-01-01T00:00:00.000Z
const json = JSON.stringify(person);
const data1 = JSON.parse(json);
const data2 = JSON.parse(json, (key, value) => {
if (key[0] === "_") return undefined;
if (
typeof value === "string" &&
/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/.test(value)
) {
return new Date(value);
}
return value;
});
console.log(data1); // { name: 'Aatrox', birth: '1970-01-01T00:00:00.000Z' }
console.log(data2); // { name: 'Aatrox', birth: 1970-01-01T00:00:00.000Z }
console.log(data1.birth instanceof Date); // false
console.log(data2.birth instanceof Date); // true
❌ 국제화 API
TODO: 나중에 필요해서 사용해보고 나서 작성
✍️ 콘솔 API
0️⃣ console.assert()
첫 번째 인자가 true
면 아무것도 하지 않고, false
면 Assertion failed
가 붙은 에러처럼 표시됩니다.
( 실제로 예외를 일으키지는 않습니다. )
1️⃣ console.clear()
가능하다면 콘솔을 비웁니다.
2️⃣ console.table()
객체나 배열같은 데이터를 표 형태로 출력합니다.
표 형태로 출력이 불가능하다면 console.log()
로 출력합니다.
3️⃣ console.trace()
스택을 추적한 결과를 보여줍니다.
4️⃣ console.count()
값을 인자로 받아서 그 값이 호출된 횟수를 출력합니다.
5️⃣ console.countReset()
값을 인자로 받아서 그 값의 카운터를 초기화합니다.
6️⃣ console.group(), console.groupCollapsed(), console.groupEnd()
console.group()
:console.groupEnd()
가 나올 때까지 호출한 메시지를 하나의 그룹으로 묶어서 들여쓰기 및 접기/펴기가 가능하도록 출력합니다.console.groupCollapsed()
:console.group()
와 같고 접힌 상태로 출력됩니다.groupEnd()
: 그룹의 끝을 의미하며 가장 최근의 그룹을 닫습니다.
7️⃣ console.time(), console.timeLog(), console.timeEnd()
console.time()
: 인자를 하나 받고 시작 시간을 기록합니다.console.timeLog()
: 인자를 하나 받고 그 인자에 해당하는console.time()
가 있다면 경과 시간을 출력합니다.console.timeEnd()
: 인자를 하나 받고 그 인자에 해당하는console.time()
가 있다면 경과 시간을 출력하고 타이머가 종료됩니다.
☔ URL API
URL
을 분석/검색/수정 등의 많은 처리를 쉽게 할 수 있도록 도와주는 클래스입니다.
0️⃣ URL 사용 방법
1
2
3
4
5
6
7
8
9
10
11
const url = new URL("https://1-blue.github.io:80/posts/Redux-Toolkit?q=redux&w=toolkit#RTK");
console.log(url.href); // https://1-blue.github.io:80/posts/Redux-Toolkit?q=redux&w=toolkit#RTK
console.log(url.origin); // https://1-blue.github.io:80
console.log(url.protocol); // https:
console.log(url.host); // 1-blue.github.io:80
console.log(url.hostname); // 1-blue.github.io
console.log(url.port); // 80
console.log(url.pathname); // /posts/Redux-Toolkit
console.log(url.search); // ?q=redux&w=toolkit
console.log(url.hash); // #RTK
1️⃣ URL 수정
origin
만 읽기 전용이고 나머지는 모두 수정할 수 있습니다.
또한 URL
에 들어갈 수 없는 문자들은 자동으로 이스케이프하는 것도 유용합니다.
1
2
3
4
5
6
7
const url = new URL("https://1-blue.github.io:80/posts/Redux-Toolkit?q=redux&w=toolkit#RTK");
url.origin = "aa";
console.log(url.origin); // https://1-blue.github.io:80
url.pathname = "/타입스크립트";
console.log(url.pathname); // /%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8
2️⃣ SearchParams와 URLSearchParams
querystring
을 사용하는 경우 유용하게 쓸 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const url = new URL("https://1-blue.github.io:80/posts/Redux-Toolkit");
console.log(url.search); // ""
url.searchParams.append("q", "react");
console.log(url.search); // "?q=react"
url.searchParams.set("q", "redux");
console.log(url.search); // "?q=redux"
console.log(url.searchParams.get("q")); // "redux"
console.log(url.searchParams.has("q")); // true
url.searchParams.append("w", "123");
url.searchParams.append("w", "456");
console.log(url.searchParams.get("w")); // 123
console.log(url.searchParams.getAll("w")); // [ '123', '456' ]
url.searchParams.sort();
console.log(url.search); // "?q=redux&w=123&w=456"
console.log(...url.searchParams); // [ 'q', 'redux' ] [ 'w', '123' ] [ 'w', '456' ]
url.searchParams.delete("w");
console.log(url.search); // ?q=redux
console.log(url.href); // https://1-blue.github.io:80/posts/Redux-Toolkit?q=redux
console.log(url.searchParams instanceof URLSearchParams); // true
3️⃣ encodeURI()와 decodeURI()
URL
을 인코딩/디코딩하는 메서드입니다.
단, URL
구분자들을 이스케이프하지 않습니다. ( /
, ?
, #
등 )
4️⃣ encodeComponentURI()와 decodeComponentURI()
위와 같은 역할의 메서드지만 URL
구분자들 모두 인코딩/디코딩한다는 차이가 있습니다.
📮 레퍼런스
- « 자바스크립트 완벽 가이드 11장 » ( 데이비드 플래너건 지음, 한성용 옮김, 인사이트, 2022 )
- 1-blue - 이터러블
- 1-blue - 정규 표현식