2020년 8월 22일

맵과 셋

지금까진 아래와 같은 복잡한 자료구조를 학습해 보았습니다.

  • 객체 – 키가 있는 컬렉션을 저장함
  • 배열 – 순서가 있는 컬렉션을 저장함

하지만 현실 세계를 반영하기엔 이 두 자료구조 만으론 부족해서 맵(Map)셋(Set)이 등장하게 되었습니다.

맵(Map)은 키가 있는 데이터를 저장한다는 점에서 객체와 유사합니다. 다만, 은 키에 다양한 자료형을 허용한다는 점에서 차이가 있습니다.

맵에는 다음과 같은 주요 메서드와 프로퍼티가 있습니다.

  • new Map() – 맵을 만듭니다.
  • map.set(key, value)key를 이용해 value를 저장합니다.
  • map.get(key)key에 해당하는 값을 반환합니다. key가 존재하지 않으면 undefined를 반환합니다.
  • map.has(key)key가 존재하면 true, 존재하지 않으면 false를 반환합니다.
  • map.delete(key)key에 해당하는 값을 삭제합니다.
  • map.clear() – 맵 안의 모든 요소를 제거합니다.
  • map.size – 요소의 개수를 반환합니다.

예시:

let map = new Map();

map.set('1', 'str1');   // 문자형 키
map.set(1, 'num1');     // 숫자형 키
map.set(true, 'bool1'); // 불린형 키

// 객체는 키를 문자형으로 변환한다는 걸 기억하고 계신가요?
// 맵은 키의 타입을 변환시키지 않고 그대로 유지합니다. 따라서 아래의 코드는 출력되는 값이 다릅니다.
alert( map.get(1)   ); // 'num1'
alert( map.get('1') ); // 'str1'

alert( map.size ); // 3

맵은 객체와 달리 키를 문자형으로 변환하지 않습니다. 키엔 자료형 제약이 없습니다.

map[key]Map을 쓰는 바른 방법이 아닙니다.

map[key] = 2로 값을 설정하는 것 같이 map[key]를 사용할 수 있긴 합니다. 하지만 이 방법은 map을 일반 객체처럼 취급하게 됩니다. 따라서 여러 제약이 생기게 되죠.

map을 사용할 땐 map전용 메서드 set, get 등을 사용해야만 합니다.

맵은 키로 객체를 허용합니다.

예시:

let john = { name: "John" };

// 고객의 가게 방문 횟수를 세본다고 가정해 봅시다.
let visitsCountMap = new Map();

// john을 맵의 키로 사용하겠습니다.
visitsCountMap.set(john, 123);

alert( visitsCountMap.get(john) ); // 123

객체를 키로 사용할 수 있다는 점은 의 가장 중요한 기능 중 하나입니다. 객체에는 문자열 키를 사용할 수 있습니다. 하지만 객체 키는 사용할 수 없습니다.

객체형 키를 객체에 써봅시다.

let john = { name: "John" };

let visitsCountObj = {}; // 객체를 하나 만듭니다.

visitsCountObj[john] = 123; // 객체(john)를 키로 해서 객체에 값(123)을 저장해봅시다.

// 원하는 값(123)을 얻으려면 아래와 같이 키가 들어갈 자리에 `object Object`를 써줘야합니다.
alert( visitsCountObj["[object Object]"] ); // 123

visitsCountObj는 객체이기 때문에 모든 키를 문자형으로 변환시킵니다. 이 과정에서 john은 문자형으로 변환되어 "[object Object]"가 됩니다.