# Map

## 1. 개요

ES6부터 도입된 자바스크립트의 객체인 맵(Map)과 셋(Set)은 기존의 자료구조인 객체와 배열과 비슷하지만 차이점이 분명 존재합니다. 이번 챕터에서는 객체와 배열과 다른 맵과 셋의 특징을 알아보자.

***

## 2. Object vs Map

* Object의 키는 String이며, Map은 문자열이 아닌 값도 키로 설정할 수 있다.
* Map은 크기를 간단한 방법으로 가져올 수 있다.
* Map은 추가된 순서대로 반복한다.

***

## 3. 맵(Map) 객체 생성

맵은 키가 있는 데이터를 저장한다는 점에서 객체와 유사하지만 맵은 키에 다양한 자료형을 허용한다는 점에서 차이가 있다.

먼저 맵 객체 생성하는 방법에 대해 알아보자.

### 3-1. 빈 Map 객체 생성

```javascript
let map = new Map();
```

![map\_obj\_create](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-077824b0773d2d006642c6e6e914e5a941223afa%2Fmap_object_create1.png?alt=media)

***

### 3-2. \[키, 값] 형태의 중첩 배열을 전달하여 Map 객체 생성

1.  기본 생성 방법

    ```javascript
    let map = new Map([
      ["A", "valueA"],
      ["B", "valueB"],
      ["C", "valueC"],
    ]);
    ```

    <img src="https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-bb990c9929ece0bd18756b7b43e39c91f430ed9a%2Fmap_object_create2.png?alt=media" alt="map_obj_create 2" data-size="original">
2.  만약, 중복되는 키가 존재할 경우 마지막 값이 적용된다.

    ```javascript
    let map = new Map([
      ["A", "valueA"],
      ["B", "valueB"],
      ["C", "valueC"],
      ["B", "valueBB"],
    ]);
    ```

    <img src="https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-a4421c8112e5449e96739b0f367e51b9e03b750e%2Fmap_object_create3.png?alt=media" alt="map_object_create 2" data-size="original">
3.  \[키, 값]에서 값은 객체가 될 수 있다.

    ```javascript
    let map = new Map([
      ["A", { value: "valueA" }],
      ["B", { value: "valueB" }],
      ["C", { value: "valueC" }],
    ]);
    ```

    <img src="https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-9e00c0c951a2b29f9c7a176b452283875d775972%2Fmap_object_create4.png?alt=media" alt="map_object_create 4" data-size="original">
4.  \[키, 값]에서 키도 객체가 될 수 있지만 고유한 값이 될 수 없다.

    ```javascript
    let map = new Map([
      [{ key: "A" }, { value: "valueA" }],
      [{ key: "B" }, { value: "valueB" }],
      [{ key: "C" }, { value: "valueC" }],
      [{ key: "B" }, { value: "valueBB" }],
    ]);
    ```

    <img src="https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-50e9c92dbb9b2d52f64e965be99e9ebd9a501285%2Fmap_object_create5.png?alt=media" alt="map_object_create 5" data-size="original">

***

### 3-3. Map.set(key, value): key를 이용해 value를 저장

1.  기본 사용 방법

    ```javascript
    let map = new Map();
    map.set("A", "valueA");
    map.set("B", "valueB");
    map.set("C", "valueC");
    ```

    <img src="https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-6dee41ab60b01f4d32d748c8c3bdf01f2a3809ce%2Fmap_object_create6.png?alt=media" alt="map_object_create 6" data-size="original">
2.  체이닝 방법

    `map.set`을 호출할 때마다 맵 자신이 반환된다. 이를 이용하여 `map.set`을 체이닝(chaining)할 수 있다.

    ```javascript
    let map = new Map();
    map.set("A", "valueA").set("B", "valueB").set("C", "valueC");
    ```

    <img src="https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-2cb24cf4717fe30f722f6d50068883f9812eb948%2Fmap_object_create7.png?alt=media" alt="map_object_create 7" data-size="original">

***

### 3-4. Object.entries(obj): 평범한 객체를 가지고 맵(Map) 만들기

평범한 객체를 가지고 `맵(Map)`을 만들고 싶으면 내장 메서드 `Object.entries(obj)`를 활용해야 한다. 이 메서드는 객체의 키-값 쌍을 요소(`[key, value]`)로 가지는 배열을 반환한다.

예를 들어 아래와 같은 평범한 객체가 있다.

```javascript
const obj = {
  name: "HD",
  age: 29,
  gender: "male",
};
```

위의 `obj`객체를 `Object.entries(obj)`의 인자로 넣게 되면 키-값 쌍을 요소(`[key, value]`)로 가지는 배열을 반환한다. (아래의 코드 및 사진 참고)

```javascript
const entries = Object.entries(obj);
```

![map\_object\_create 8](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-41cbb64fa93e0ccddb6123ba9c01b010db2d75bb%2Fmap_object_create8.png?alt=media)

`entreis`은 각 요소가 \[키, 값] 쌍인 배열이다. 그러므로 `new Map()`에 전달하여 새로운 맵을 만들 수 있다.

```javascript
const map = new Map(entries);
```

![map\_object\_create 9](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-faba1932c12c0669d732ed0d6703f3d1229301f4%2Fmap_object_create9.png?alt=media)

***

## 4. Map의 주요 메서드와 프로퍼티

### 4-1. Map.get(key)

`key`에 해당하는 값을 반환한다. `key`가 존재하지 않으면 `undefined`를 반환한다.

```javascript
let map = new Map();
map.set("name", "HD").set("age", 29);

console.log(map.get("name"));
console.log(map.get("gender"));
```

![map\_get](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-35a8b48fed4be0eeb8ff6c388251e6540b885875%2Fmap_get.png?alt=media)

> `map`을 사용할 땐 `map`전용 메서드 `set`, `get` 등을 사용하자. 기존 객체에서 사용했던 방법은 `map`을 일반 객체처럼 취급하게 되어 여러 제약이 생긴다.

***

### 4-2. Map.has(key)

`key`가 존재하면 `true`, 존재하지 않으면 `false`를 반환한다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

console.log(map.has("A"));
console.log(map.has("C"));
console.log(map.has("F"));
```

![map\_has](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-3971d6882614a05c3547879b038446796509b7bd%2Fmap_has.png?alt=media)

***

### 4-3. Map.delete(key)

`key`에 해당하는 값을 삭제한다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

console.log(map.has("C"));
map.delete("C");
console.log(map.has("C"));
```

![map\_delete](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-68d8b67fefc877dccac1a3dc2ed965dbdcb52bb2%2Fmap_delete.png?alt=media)

***

### 4-4. Map.clear()

맵 안의 모든 요소를 제거한다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

map.clear();
console.log(map);
```

![map\_clear](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-af5479a1cf3a8dab1a608ddb6c24fc58cb0bfe3d%2Fmap_clear.png?alt=media)

***

### 4-5. Map.size

요소의 개수를 반환한다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

console.log(map.size);
```

![map\_size](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-37ccd3558ec6730df3061b329202d4fff586c40c%2Fmap_size.png?alt=media)

***

### 4-6. Map.keys()

각 요소의 키를 모은 반복 가능한(iterable, 이터러블) 객체를 반환한다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

console.log(map.keys());
```

![map\_keys](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-20d7b8cd1ada0e19445b02dfbefd1cc1bf9c84b7%2Fmap_keys.png?alt=media)

***

### 4-7. Map.values()

각 요소의 값을 모든 이터러블 객체를 반환한다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

console.log(map.values());
```

![map\_values](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-bea84aae102ac25f11fab66a47aea2ef41b1cc71%2Fmap_values.png?alt=media)

***

### 4-8. Map.entries()

요소의 `[키, 값]`을 한 쌍으로 하는 이터러블 객체를 반환한다. 이 이터러블 객체는 `for...of`반복문의 기초로 쓰인다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

console.log(map.entries());
```

![map\_entries](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-601ebc24085bbfe31f8635aaeeb15cea794426f3%2Fmap_entries.png?alt=media)

아래는 `for...of`반복문을 사용하여 \[키, 값] 쌍을 대상으로 순회하는 코드이다.

```javascript
for ([key, value] of map.entries()) {
  console.log(key, value);
}
for ([key, value] of map) {
  console.log(key, value);
}
```

두 반복문의 결과는 같다.

![map\_entries 2](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-ca2e8d493f24fda9f85ca975fc2a9ac1bd84a76f%2Fmap_entries2.png?alt=media)

> 맵은 배열과 유사하게 내장 메서드 `forEach`도 지원한다.
>
> ```javascript
> let map = new Map([
>   ["A", "valueA"],
>   ["B", "valueB"],
>   ["C", "valueC"],
>   ["D", "valueD"],
>   ["E", "valueE"],
> ]);
> map.forEach((value, index) => {
>   console.log("value: ", value);
>   console.log("index: ", index);
> });
> ```
>
> <img src="https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-64f62fea0dc0bf4ff239d072a89e91010f56c9b7%2Fmap_forEach.png?alt=media" alt="map_forEach" data-size="original">

***

### 4-9. Object.fromEntries

맵을 객체로 바꾸기 위해서는 `Object.fromEntries`를 사용하면 된다. 이 메서드는 각 요소가 `[키, 값]` 쌍인 배열을 객체로 바꿔준다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);

// map.entries()를 호출하면 맵의 [키, 값]을 요소로 가지는 이터러블을 반환한다.
// 이런 과정을 거치는 이유는 Object.fromEntries 메서드를 사용하기 위함이다.
const entries = map.entries();
console.log(entries);

const obj = Object.fromEntries(entries);
console.log(obj);
```

![map\_fromEntries](https://3395804243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlrW8c4MEVWoel5YVxSk%2Fuploads%2Fgit-blob-8598afc0df1b3ada72df74f9d8a31f7da72e8a93%2Fmap_fromEntries.png?alt=media)

하지만 굳이 `map.entries()`를 하지않고 `Object.fromEntries()` 메서드의 인자로 맵(Map)을 전달해도 된다.

`Object.fromEntries`는 인자로 이터러블 객체를 받기 때문에 꼭 배열을 전달해줄 필요는 없다.(맵도 이터러블 객체이다.)

즉, 아래와 같이 위의 코드를 수정할 수 있다.

```javascript
let map = new Map([
  ["A", "valueA"],
  ["B", "valueB"],
  ["C", "valueC"],
  ["D", "valueD"],
  ["E", "valueE"],
]);
const obj = Object.fromEntries(map);
```

***

## 5. Conclusion

> 옛날 `모던 자바스크립트 Deep Dive`책을 보며 공부했던 적이 있다. 그 책에 나왔던 내용 중 하나가 바로 오늘 공부한 맵(Map)에 대해 봤던 기억이 있다. 당시에는 정말 대\~\~충 보고 넘겼기 때문에 오늘 공부하면서도 많이 생소하게 느꼈다. 또한 이터러블와 같은 개념도 오랜만에 보는 것이기에 머리속이 복잡해졌다. `모던 자바스크립트 Deep Dive`책을 다시 보면서 자바스크립트의 기본기를 탄탄히 다질 수 있도록 하자. 처음부터 다시 보며 하나하나 내 것으로 만들어 보자! 아마 그 땐 알던 내용보다는 자바스크립트가 작동하는 원리, 생소한 개념을 먼저 정리하며 공부하지 않을까 싶다.\
> 맵에 대한 느낌은 반복가능한 객체이므로 `Array.forEach()`메서드를 사용할 수 있다는 점이 신기하였다. 당연히 `for...of`구문도 사용하니 코테를 풀고 공부할 때 맵을 잘 활동하도록 해야겠다.

***

## 참고

[맵과 셋](https://ko.javascript.info/map-set#ref-3157)\
[\[JavaScript\]Map 객체](https://developer-talk.tistory.com/170)

***

📅 2022-08-08
