[JavaScript] Map과 Set

iberis2·2023년 1월 8일
0

객체(Object)의 한계

  1. 객체에 새로운 프로퍼티를 추가할 때, 중복되는 이름(key)이 이미 있어도 에러가 발생하지 않고, 기존 프로퍼티 값을 새롭게 덮어쓴다.
  2. 객체의 key는 항상 문자열 타입만 가능하다.
  3. 일반 객체는 iterible 하지 않아 for of 문을 사용할 수 없다.
  4. 프로퍼티들의 순서가 보장되지 않는다.

Map

Map은 키로 구성된 값의 집합이며 각 키는 다시 다른 값과 연결된다.

일반 객체보다 Map을 사용하는 게 더 유리한 경우
1. 문자열이 아닌 key를 등록할 떄
2. 자료 구조에 등록된 key들의 순서가 중요할 때
3. 저장해야할 데이터 양이 객체가 최대로 담을 수 있는 양보다 많을 때

  • 객체는 1,100만개 프로퍼티를 담을 수 있지만, Map은 1,600만개를 담을 수 있다.

Map의 메소드

  • map.set(key, value): key를 이용해 vlaue를 추가하는 메소드
  • map.get(key): key에 해당하는 값을 얻는 메소드
    key가 존재하지 않으면 undefined를 반환
    • === 로 일치여부를 판단하므로 참조값(배열, 객체 등)은 정확히 같은 참조를 전달해야한다.
  • map.has(key): key가 존재하면 true, 존재하지 않으면 false를 반환하는 메소드
  • map.delete(key): key에 해당하는 값을 삭제하는 메소드
  • map.clear(): Map 안의 모든 요소를 제거하는 메소드
  • map.size: 요소의 개수를 반환하는 프로퍼티
    [주의]메소드가 아님! 주배열의 length 프로퍼티와 같은 역할
//new Map() 새로운 Map 생성, 배열을 선택적 파라미터로 받는다
let m = new Map([
  ["one", 1],
  [2, "two"],
]);
console.log(m); // Map(2) { 'one' => 1, 2 => 'two' }

// 객체의 프로퍼티를 복사할 수도 있다.
let obj = { x: 1, y: 2 };
let copy = new Map(Object.entries(obj));
console.log(copy); // Map(2) { 'x' => 1, 'y' => 2 }
let myMap = new Map();
console.log(myMap); // Map(0) {}
// 기본적으로 길이도 같이 출력된다.

// map.set(key, value) 프로퍼티 추가
// 문자열만 key 값으로 지정가능한 객체와는 다르게 다양한 자료형을 key로 사용할 수 있다.
myMap.set("1", "문자열 1");
myMap.set(2, "숫자형 2");
myMap.set(true, "불린형 true");
console.log(myMap); // Map(3) { '1' => '문자열 1', 2 => '숫자형 2', true => '불린형 true' }

/* set() 메서드는 체인으로 연결할 수도 있다.
myMap = new Map().set("1", "문자열 1").set(2, "숫자형 2").set(true, "불린형 true");
위와 동일한 결과가 나온다.*/

// map.get(key) 프로퍼티 값 반환, key가 존재하지 않으면 undefined 반환
console.log(myMap.get(2)); // 숫자형 2
console.log(myMap.get("2")); // undefined

// 일반 객체처럼 할당 및 호출도 가능한 것 처럼 보이지만, 실제 Map 으로 등록되지 않는다.
myMap.greeting = "Hello";
console.log(myMap.greeting); // Hello
console.log(myMap);
/*
Map(3) {
  '1' => '문자열 1',
  2 => '숫자형 2',
  true => '불린형 true',
  greeting: 'Hello'
} */

// map.size 프로퍼티의 개수 반환
console.log(myMap.size); // 3

// map.has(key) key가 존재하면 true, 없으면 false
console.log(myMap.has("greeting")); // false
console.log(myMap.has("1")); // true

// map.values() 프로퍼티 value 확인할 수 있는 이터러블 객체 반환
console.log(myMap.values()); // [Map Iterator] { '문자열 1', '숫자형 2', '불린형 true' }

// map.keys() 프로퍼티 key 확인할 수 있는 이터러블 객체 반환
console.log(myMap.keys()); // [Map Iterator] { '1', 2, true }

// map. entries() 전체 확인할 수 있는 이터러블 객체 반환
// [...map] 로 map을 직접 순회하는 것과 차이가 없다.
console.log(myMap.entries()); 
// [Map Entries] {[ '1', '문자열 1' ], [ 2, '숫자형 2' ], [ true, '불린형 true' ]}
m = [...myMap];
console.log(m); 
// [ [ '1', '문자열 1' ], [ 2, '숫자형 2' ], [ true, '불린형 true' ] ]

// map.forEach(value, key)
myMap.forEach((value, key)=>{
  console.log(`key: ${key}, value${value}`);
});
/*
key: 1, value문자열 1
key: 2, value숫자형 2
key: true, value불린형 true
*/

// map.delete(key) 프로퍼티 삭제
myMap.delete(true);
console.log(myMap); // Map(2) { '1' => '문자열 1', 2 => '숫자형 2', greeting: 'Hello' }

// 객체로 추가한 프로퍼티는 객체처럼 삭제
delete myMap.greeting;
console.log(myMap); // Map(2) { '1' => '문자열 1', 2 => '숫자형 2' }

// map.clear() 맵 안의 모든 프로퍼티 삭제
myMap.clear();
console.log(myMap); // Map(0) {}

Set

Set은 중복되지 않는 값으로만 이루어진 컬렉션이다.

Set의 메소드

  • set.add(value): 값을 추가하는 메소드
    메소드를 호출한 자리에는 추가된 값을 가진 Set 자신을 반환
    • set.add().add() 체인으로 연결할 수 있다.
    • 배열을 받으면 요소가 아닌 배열 자체를 추가한다.
  • set.has(value): Set 안에 값이 존재하면 true, 아니면 false를 반환하는 메소드
    • 일치 여부를 === 로 엄격하게 체크한다.
  • set.delete(value): 값을 제거하는 메소드
    메소드를 호출한 자리에는 set 내에 값이 있어서 제거에 성공하면 true, 아니면 false를 반환
    • 배열, 객체와 같은 참조값을 삭제하려면 같은 객체를 가리키는 참조를 삭제해야한다.
  • set.clear(): Set 안의 모든 요소를 제거하는 메소드
  • set.size: 요소의 개수를 반환하는 프로퍼티
    [주의] 메소드가 아님 배열의 length 프로퍼티와 같은 역할
// 배열, Set, 이터러블 객체를 파라미터로 Set을 생성할 수 있다.
const s = new Set([1, "s"]);
console.log(s); // Set(2) { 1, 's' }

const mySet = new Set();
console.log(mySet); // Set(0) {}

// 요소 추가
mySet.add(1);
mySet.add("a");

// 중복되는 값은 추가되지 않는다.
mySet.add(1);
console.log(mySet); // Set(2) { 1, 'a' }

// 여러 값 넣어도 첫 번째 값만 추가된다.
mySet.add(2, "b", 3, s);
console.log(mySet); // Set(3) { 1, 'a', 2 }

// 체인으로 연결할 수 있다.
mySet.add("b").add(3).add(s);
console.log(mySet); // Set(6) { 1, 'a', 2, 'b', 3, Set(2) { 1, 's' } }

// 개수(size) 확인
console.log(mySet.size); // 6

// 삭제 : delete는 한 번에 1개씩만 삭제하며, boolean 값을 반환한다.
let d = mySet.delete(1, s);
console.log(d); // true
console.log(mySet); // Set(5) { 'a', 2, 'b', 3, Set(2) { 1, 's' } }

// 참조값은 정확히 같은 참조를 전달해야 삭제할 수 있다.
d = mySet.delete(s);
console.log(mySet); // Set(4) { 'a', 2, 'b', 3 }

d = mySet.delete(10);
console.log(d); // false
console.log(mySet); // Set(4) { 'a', 2, 'b', 3 }

// d  = mySet.delete(s);
// 체인으로 연결할 수 없다.
// mySet.delete(2).delete(3); // TypeError: mySet.delete(...).delete is not a function

// Set의 요소인지 확인
console.log(mySet.has(1)); // false
console.log(mySet.has("a")); // true

// 모든 요소 제거
mySet.clear();
console.log(mySet); // Set(0) {}
profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글