각 원소를 고유하게(= 중복 없이) 저장하는 객체이다.
// 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"} => 중복 추가되지 않음
// 원소 추가하기
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은 반복이 가능하다. 반복하는 방법에는 2가지가 있다.
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 (const person of family) {
console.log(person);
}
// Dad
// Mom
중복 없이 고유한 값만 보유한다는 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"]
Set과 유사하지만 WeakSet은 객체만 포함할 수 있는 Set이다.
(객체를 여러 개 넣을 때는 배열이라는 뜻으로 대괄호로 감싸줌)
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이 갖고 있는 객체에 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은 키/값 쌍으로 이루어진다. (<-> Set에는 키가 없음)
// Map 객체 생성하기
const family = new Map();
// 원소 추가하기 (=> Set은 .add())
family.set("Dad", 50);
family.set("Mom", 45);
family; // Map { "Dad" => 50, "Mom" => 45 }
// Map의 크기 가져오기 (= Set과 동일)
Map.size; // 2
메서드나 루프로 반복하는 방법만 보자면 (iterator 생성 및 .next() 사용 제외)
Set 객체는 for-of 반복문만 사용 가능하다.
하지만 Map 객체는 for-of 문과 함께 forEach 메서드도 사용할 수 있다.
for (const [key, val] of family) {
console.log(key, val);
}
// Dad 50
// Mom 45
family.forEach((key, val) => console.log(key, val));
// Dad 50
// Mom 45
WeakMap은 값만 있는 WeakSet과 달리 키/값 쌍으로 이루어져 있다.
이때 주의할 점은 키가 객체여서 WeakSet의 값처럼 약하게 참조된다.
WeakMap도 WeakSet과 마찬가지로 반복이 불가능하다.
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 {}
let dad = { name: "Daddy" };
const dadMap = new Map();
dadMap.set(dad, "my father");
console.log(dadMap); // Map {{...}}
// null을 할당
dad = null;
// 몇십 초 정도 기다린 뒤 다음을 실행하면 원소가 그대로 남아 있다.
console.log(dadMap); // Map {{...}}