Set, WeakSet, Map, WeakMap

Sheryl Yun·2022년 10월 15일
1
post-thumbnail

Set

각 원소를 고유하게(= 중복 없이) 저장하는 객체이다.

// Set 생성하기
const family = new Set();

// 원소 추가하기
family.add("Dad");
console.log(family); // Set {"Dad"}

family.add("Mom");
console.log(family); // Set {"Dad", "Mom"}

// 이미 추가했던 원소를 또 추가해도
family.add("Dad");
console.log(family); // Set {"Dad", "Mom"} => 중복 추가되지 않음

Set의 다양한 메서드

// 원소 추가하기
family.add("Son"); // Set {"Dad", "Mom", "Son"}

// 크기 가져오기 (.length와 동일)
family.size; // 3

// 원소 1개 삭제
family.delete("Dad"); // Set {"Mom", "Son"}

// 원소 전체 삭제
family.clear(); // Set {}

Set에는 키가 없다.
따라서 .keys()와 .entries()의 결과는 .values()와 똑같다. (= value만 출력함)

// Set.keys()
family.keys(); // SetIterator {"Dad", "Mom"}

// Set.values()
family.values(); // SetIterator {"Dad", "Mom"}

// Set.entries()
family.entries(); // SetIterator {"Dad", "Mom"}

Set 반복하기

Set은 반복이 가능하다. 반복하는 방법에는 2가지가 있다.

  1. .values()로 iterator 객체를 만들고 .next()로 반복
  2. for-of 반복문으로 반복

iterator와 .next()를 이용하여 반복

const iterator = family.values(); // .values()로 .next() 호출이 가능한 iterator 객체 생성

iterator.next(); // { value: "Dad", done: false }
iterator.next(); // { value: "Mom", done: false }
iterator.next(); // { value: undefined, done: true }

for-of 문으로 반복

for (const person of family) {
	console.log(person);
}

// Dad
// Mom

Set 활용: 배열에서 중복 제거

중복 없이 고유한 값만 보유한다는 Set의 특징을 활용하여 중복이 제거된 배열을 얻을 수 있다.

// 중복이 포함된 배열
const familyMembers = ["dad", "mom", "son", "dad", "mom", "daughter"];

 // 배열을 Set으로 만든다. (=> 중복이 제거됨)
const familySet = new Set(familyMembers);

console.log(familySet); // Set {"dad", "mom", "son", "daughter"}

// 중복이 제거된 Set을 다시 배열로 만든다. (=> 중복이 제거된 배열 반환)
const uniqueMembers = Array.from(familySet); // ["dad", "mom", "son", "daughter"] 

---------------------------------------------------------------------------------

// 위의 과정을 한 번에 하기
const uniqueMembers = Array.from(new Set(familyMembers));
console.log(uniqueMembers); // ["dad", "mom", "son", "daughter"] 

WeakSet

Set과 유사하지만 WeakSet은 객체만 포함할 수 있는 Set이다.
(객체를 여러 개 넣을 때는 배열이라는 뜻으로 대괄호로 감싸줌)

WeakSet은 반복 불가

WeakSet은 반복이 불가능하다.
for-of 문과 같은 반복문으로 작동시키면 에러가 발생한다.

let dad = { name: "Daddy", age: 50 };
let mom = { name: "Mummy", age: 45 };

const family = new WeakSet([ dad, mom ]); // 배열을 넣어도 반복 불가

for (const person of family) {
	console.log(person); // 에러 발생: family is not iterable
}

WeakSet은 약한 참조

만약 WeakSet이 갖고 있는 객체에 null이 할당되어 가비지 컬렉터(GC)에 의해 삭제되면
해당 객체는 WeakSet에서도 자동으로 삭제된다.

이는 WeakSet이 약한 참조(= 객체 값의 주소만 저장)를 하기 때문이다.
참조를 잃으면 주소를 잃어버려 본래 주소에 연결되어 있던 값을 찾을 수 없게 된다.

let dad = { name: "Daddy", age: 50 };
let mom = { name: "Mummy", age: 45 };

const family = new WeakSet([ dad, mom ]);

// null을 할당 -> 가비지 컬렉터가 수거
dad = null;

// 몇십 초 정도 기다린 뒤 다음을 실행하면 dad 원소가 사라져 있어 원소가 1개이다.
console.log(family); // WeakSet {{...}}

Map

Map은 키/값 쌍으로 이루어진다. (<-> Set에는 키가 없음)

// Map 객체 생성하기
const family = new Map();

Map의 다양한 메서드

// 원소 추가하기 (=> Set은 .add())
family.set("Dad", 50);
family.set("Mom", 45);
family; // Map { "Dad" => 50, "Mom" => 45 }

// Map의 크기 가져오기 (= Set과 동일)
Map.size; // 2

Map 반복하기

메서드나 루프로 반복하는 방법만 보자면 (iterator 생성 및 .next() 사용 제외)
Set 객체는 for-of 반복문만 사용 가능하다.

하지만 Map 객체는 for-of 문과 함께 forEach 메서드도 사용할 수 있다.

for-of 문으로 반복

for (const [key, val] of family) {
	console.log(key, val);
}

// Dad 50
// Mom 45

forEach 메서드로 반복

family.forEach((key, val) => console.log(key, val));

// Dad 50
// Mom 45

WeakMap

WeakMap은 값만 있는 WeakSet과 달리 키/값 쌍으로 이루어져 있다.
이때 주의할 점은 키가 객체여서 WeakSet의 값처럼 약하게 참조된다.

WeakMap은 반복 불가

WeakMap도 WeakSet과 마찬가지로 반복이 불가능하다.

WeakMap은 약한 참조

WeakMap에서 키로 사용된 객체가 가비지 컬렉터에 의해 수거되면(= 참조가 손실되면)
해당 키와 키의 값이 함께 WeakMap에서 자동으로 제거된다.

let dad = { name: "Daddy" };

const dadWeakMap = new WeakMap();

dadWeakMap.set(dad, "my father");

console.log(dadWeakMap); // WeakMap {{...}}

// null을 할당 -> 가비지 컬렉터가 수거
dad = null;

// 몇십 초 정도 기다린 뒤 다음을 실행하면 원소가 사라져 있다.
console.log(dadWeakMap); // WeakMap {}

유의: Map은 약한 참조가 아니다

let dad = { name: "Daddy" };

const dadMap = new Map();

dadMap.set(dad, "my father");

console.log(dadMap); // Map {{...}}

// null을 할당
dad = null;

// 몇십 초 정도 기다린 뒤 다음을 실행하면 원소가 그대로 남아 있다.
console.log(dadMap); // Map {{...}}
profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글