자바스크립트 완벽 가이드 11장 정리 ( Standard Library )
포스트
취소

자바스크립트 완벽 가이드 11장 정리 ( Standard Library )

해당 포스트는 자바스크립트 완벽 가이드라는 교재로 스터디를 하면서 11장을 정리한 포스트입니다.
주관적으로 해석한 내용이 들어가 있어서 잘못된 내용이 포함될 수 있습니다.
또한 교재의 모든 내용을 정리하지 않고 주관적인 판단에 의해 필요한 내용만 작성했습니다.

🗃️ Map과 Set

JavaScript의 객체의 keystring or symbol이어야 하는 제약이 있어 ES6에 추가된 스펙입니다.

0️⃣ Set

배열과 같은 값의 집합입니다.

  • 특징
    1. 중복을 허용하지 않음
    2. 순서가 없어서 인덱스가 존재하지 않음 ( 하지만 순서는 기억하고 있음 )
    3. 이터러블하고 이터러블을 인자로 받음
    4. size, add(), delete(), clear(), has(), forEach()
    5. 요소를 검사할 때는 엄격하게 검사함 ( ===처럼 검사 )
    6. 요소 검사는 속도가 매우 빠름 ( 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를 사용할 수 있습니다.

  • 특징
    1. 인자는 [key, value]형태 혹은 [key, value]의 이터러블로 받음
    2. keyvalue가 연결된 것일 뿐 집합이 아님
    3. 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입니다.

  • 특징
    1. 객체 타입을 요소로 받음 ( 가비지 컬렉터의 대상이 되는 값 )
    2. add(), has(), delete() 메서드만 존재
    3. 요소의 길이가 가변적이기 때문에 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입니다.

  • 특징
    1. key는 반드시 객체나 배열같은 객체 타입이어야 함 ( 가비지 컬렉터의 대상이 되는 값 )
    2. get(), set(), has(), delete() 메서드만 존재
    3. 이터러블이 아님
    4. 요소의 길이가 가변적이기 때문에 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 생성자

현재 동작하는 시스템의 시간을 기준으로 계산합니다.

  • 인자
    1. 인자로 숫자를 받으면 1970년 1월 1일 이후 지난 시간을 나타내는 숫자로 간주함
    2. 년, 월, 일, 시, 분, 초, 밀리초 형태로 값을 받을 수 있음 ( 월은 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면 아무것도 하지 않고, falseAssertion 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 구분자들 모두 인코딩/디코딩한다는 차이가 있습니다.

📮 레퍼런스

  1. « 자바스크립트 완벽 가이드 11장 » ( 데이비드 플래너건 지음, 한성용 옮김, 인사이트, 2022 )
  2. 1-blue - 이터러블
  3. 1-blue - 정규 표현식
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

Tree Shaking

웹팩 ( Webpack + TypeScript + React )