[Modern JS] #37 Set과 Map - (2)

wonnie1224·2022년 8월 3일
0

Modern JS

목록 보기
5/7

37.2 Map

  • Map 객체 : 키(key)와 값(value)의 쌍으로 이루어진 컬렉션
  • 객체와 유사 but 차이가 있음

<객체 vs. Map 객체>

구분객체Map 객체
key로 사용할 수 있는 값문자열 or 심벌 값객체를 포함한 모든 값
이터러블XO
요소 개수 확인Object.keys(obj).lengthmap.size

37.2.1 Map 객체의 생성

  • Map 생성자 함수로 생성함

1) 인수를 전달 X : 빈 Map 객체가 생성됨

const map = new Map();
console.log(map); // Map(0) {}

2) 이터러블을 인수로 전달받아 Set 객체 생성

  • 이때 이터러블은 key & value가 쌍으로 이루어진 요소로 구성돼야 함
const map1 = new Map([['key1', 'value1'], ['key2', 'value2']]);
console.log(map1); // Map(2) {"key1" => "value1", "key2" => "value2"}

// 키 & 값 쌍으로 안 넣은 경우
const map2 = new Map([1, 2]); // TypeError: Iterator value 1 is not an entry object
  • 중복된 key를 갖는 요소 존재 -> value가 덮어써짐
    => Map 객체엔 중복된 키를 갖는 요소 존재할 수 X
const map = new Map([['key1', 'value1'], ['key1', 'value2']]);
console.log(map); // Map(1) {"key1" => "value2"}
// 값이 'value2'로 덮어써짐

37.2.2 요소 개수 확인

  • Map.prototype.size 프로퍼티 사용
const { size } = new Map([['key1', 'value1'], ['key2', 'value2']]);
console.log(size); // 2
  • size 프로퍼티 - setter 함수 없이 getter 함수만 존재하는 접근자 프로퍼티
    => size 프로퍼티에 숫자 할당해서 Set 객체의 요소 개수 변경 불가능
const map = new Map([['key1', 'value1'], ['key2', 'value2']]);

console.log(Object.getOwnPropertyDescriptor(Map.prototype, 'size'));
// {set: undefined, enumerable: false, configurable: true, get: ƒ}

map.size = 10; // 무시된다.
console.log(map.size); // 2

37.2.3 요소 추가

  • Map 객체에 요소 추가할 땐 Map.prototype.set 메서드 사용
const map = new Map();
console.log(map); // Map(0) {}

map.set('key1', 'value1');
console.log(map); // Map(1) {"key1" => "value1"}
  • set 메서드 : 새로운 요소가 추가된 Map 객체 반환함
    -> set 메서드를 연속적으로 호출 가능
const map = new Map();

map
  .set('key1', 'value1')
  .set('key2', 'value2');

console.log(map); // Map(2) {"key1" => "value1", "key2" => "value2"}
  • Map 객체에 중복된 key를 갖는 요소 존재할 수 X
    -> 중복된 key를 갖는 요소 추가하면 에러 없이 value가 덮어써짐
const map = new Map();

map
  .set('key1', 'value1')
  .set('key1', 'value2');

console.log(map); // Map(1) {"key1" => "value2"}
  • Map 객체는 NaN과 NaN, +0과 -0은 같다고 평가 -> 중복 추가 허용 X
    *) 일치 비교 연산자 (===)와의 차이 : (===)는 NaN과 NaN은 다름, +0과 -0은 같다고 평가
const map = new Map();

console.log(NaN === NaN); // false
console.log(0 === -0); // true

// NaN과 NaN을 같다고 평가하여 중복 추가를 허용하지 않는다.
map.set(NaN, 'value1').set(NaN, 'value2');
console.log(map); // Map(1) { NaN => 'value2' }

// +0과 -0을 같다고 평가하여 중복 추가를 허용하지 않는다.
map.set(0, 'value1').set(-0, 'value2');
console.log(map); // Map(2) { NaN => 'value2', 0 => 'value2' }
  • Map 객체는 key 타입에 제한 없음 -> 객체를 포함한 모든 값을 key로 사용 가능
    (일반 객체와의 차이점임)
const map = new Map();

const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

// 객체도 키로 사용할 수 있다.
map
  .set(lee, 'developer')
  .set(kim, 'designer');

console.log(map);
// Map(2) { {name: "Lee"} => "developer", {name: "Kim"} => "designer" }

37.2.4 요소 취득 - Set 객체와 다른 점!

  • Map 객체에서 특정 요소 취득할 땐 Map.prototype.get 메서드 사용
const map = new Map();

const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

map
  .set(lee, 'developer')
  .set(kim, 'designer');

console.log(map.get(lee)); // developer
console.log(map.get('key')); // undefined

37.2.5 요소 존재 여부 확인

  • Map 객체에 특정 요소가 존재하는지 확인할 땐 Map.prototype.has 메서드 사용
  • has 메서드 : 특정 요소의 존재 여부 나타내는 불리언 값 반환
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

const map = new Map([[lee, 'developer'], [kim, 'designer']]);

console.log(map.has(lee)); // lee가 있으므로 true
console.log(map.has('key')); // 'key'가 없으므로 false

37.2.6 요소 삭제

  • Map 객체에 특정 요소를 삭제할 땐 Map.prototype.delete 메서드 사용
  • delete 메서드 : 삭제 성공 여부 나타내는 불리언 값 반환
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

const map = new Map([[lee, 'developer'], [kim, 'designer']]);

// kim이라는 key 값을 가진 key-value 쌍을 삭제
map.delete(kim);
console.log(map); // Map(1) { {name: "Lee"} => "developer" }
  • 존재하지 않는 key로 Map 객체의 요소를 삭제하려 하면 에러 없이 무시됨
const map = new Map([['key1', 'value1']]);

// 존재하지 않는 키 'key2'로 요소를 삭제하려 하면 에러없이 무시된다.
map.delete('key2');
console.log(map); // Map(1) {"key1" => "value1"}
  • delete 메서드는 삭제 성공 여부 나타내는 불리언 값 반환하므로(set 메서드처럼 Map 객체를 반환하는게 아니라서) 연속적으로 호출 불가능
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

const map = new Map([[lee, 'developer'], [kim, 'designer']]);

map.delete(lee).delete(kim); // TypeError: map.delete(...).delete is not a function

37.2.7 요소 일괄 삭제

  • Map.prototype.clear 메서드 사용
  • clear 메서드 : 항상 undefined 반환함
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

const map = new Map([[lee, 'developer'], [kim, 'designer']]);

map.clear();
console.log(map); // Map(0) {}

37.2.8 요소 순회

  • Map.prototype.forEach 메서드 사용
    : Array.prototype.forEach 메서드와 유사하게 콜백 함수 & forEach 메서드의 콜백 함수 내부에서 this로 사용될 객체(옵션)을 인수로 전달함

콜백 함수는 3개의 인수 전달받음

  • 1번째 인수 : 현재 순회 중인 요소값(value)
  • 2번째 인수 : 현재 순회 중인 요소키(key)
  • 3번째 인수 : 현재 순회 중인 Map 객체 자체
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

const map = new Map([[lee, 'developer'], [kim, 'designer']]);

map.forEach((v, k, map) => console.log(v, k, map));
/*
developer {name: "Lee"} Map(2) {
  {name: "Lee"} => "developer",
  {name: "Kim"} => "designer"
}
designer {name: "Kim"} Map(2) {
  {name: "Lee"} => "developer",
  {name: "Kim"} => "designer"
}
*/
  • Map 객체 - 이터러블임
    -> for...of문으로 순회 가능
    -> 스프레드 문법 & 배열 디스트럭처링 할당의 대상이 될 수 있음
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

const map = new Map([[lee, 'developer'], [kim, 'designer']]);

// Map 객체는 Map.prototype의 Symbol.iterator 메서드를 상속받는 이터러블이다.
console.log(Symbol.iterator in map); // true

// 이터러블인 Map 객체는 for...of 문으로 순회할 수 있다.
for (const entry of map) {
  console.log(entry); // [{name: "Lee"}, "developer"]  [{name: "Kim"}, "designer"]
}

// 이터러블인 Map 객체는 스프레드 문법의 대상이 될 수 있다.
console.log([...map]);
// [[{name: "Lee"}, "developer"], [{name: "Kim"}, "designer"]]

// 이터러블인 Map 객체는 배열 디스트럭처링 할당의 대상이 될 수 있다.
const [a, b] = map;
console.log(a, b); // [{name: "Lee"}, "developer"]  [{name: "Kim"}, "designer"]
  • Map 객체 : 이터러블이면서 이터레이터인 객체를 반환하는 메서드를 제공
    *) 34.6.3절 참고...
Map 메서드설명
Map.prototype.keysMap 객체에서 요소키를 값으로 갖는 이터러블이면서 이터레이터인 객체를 반환
Map.prototype.valuesMap 객체에서 요소값을 값으로 갖는 이터러블이면서 이터레이터인 객체를 반환
Map.prototype.entriesMap 객체에서 요소키와 요소값을 값으로 갖는 이터러블이면서 이터레이터인 객체를 반환
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };

const map = new Map([[lee, 'developer'], [kim, 'designer']]);

// Map.prototype.keys는 Map 객체에서 요소키를 값으로 갖는 이터레이터를 반환한다.
for (const key of map.keys()) {
  console.log(key); // {name: "Lee"} {name: "Kim"}
}

// Map.prototype.values는 Map 객체에서 요소값을 값으로 갖는 이터레이터를 반환한다.
for (const value of map.values()) {
  console.log(value); // developer designer
}

// Map.prototype.entries는 Map 객체에서 요소키와 요소값을 값으로 갖는 이터레이터를 반환한다.
for (const entry of map.entries()) {
  console.log(entry); // [{name: "Lee"}, "developer"]  [{name: "Kim"}, "designer"]
}
  • Map 객체는 요소의 순서에 의미 X
  • but, Map 객체를 순회하는 순서 = 요소가 추가된 순서
profile
안녕하세요😊 인공지능을 공부하고 있는 대학생입니다 🙌

0개의 댓글