Set
- Set 객체는 중복되지 않는 유일한 값들의 집합
- 배열과 유사
구분 | 배열 | Set 객체 |
---|
동일한 값을 중복하여 포함 여부 | O | X |
요소 순서에 의미 | O | X |
인덱스 요소에 접근 여부 | O | X |
Set 객체 생성
- Set 객체는 생성자 함수로 생성
- 인수를 전달하지 않으면 빈 Set 객체 생성
- Set 생성자 함수는 이터러블을 인수로 전달받아 Set 객체 생성 ( 중복된 값은 저장하지 않음 )
const set = new Set();
console.log(set);
const set1 = new Set([1, 2, 3, 4]);
console.log(set1);
const set2 = new Set('hello');
console.log(set2);
- 중복을 허용하지 않는 Set 객체의 특성을 활용하여 배열의 중복된 요소를 제거
const uniq = array => array.filter((v, i, self) => self.indexOf(v) === i);
console.log(uniq([2, 1, 2, 3, 4, 3, 4]));
const uniq = array => [...new Set(array)];
console.log(uniq([2, 1, 2, 3, 4, 3, 4]));
요소 개수 확인
- Set 객체의 요소 개수를 확인할 때 Set.prototype.size 프로퍼티 사용
- size 프로퍼티는 setter함수 없이 getter함수만 있기 때문에 요소 개수를 변경 불가
const { size } = new Set([1, 2, 3, 4]);
console.log(size);
const set = new Set([1, 2, 3]);
set.size = 10;
console.log(set.size);
요소 추가
- Set 객체에 요소를 추가할 때 Set.prototype.add 메서드 사용
- add 메서드는 새로운 요소가 추가된 Set 객체를 반환 -> 연속적 호출 가능(method chaining)
- 중복된 요소의 추가 불가 (무시됨)
- 일치 비교 연산자(===)을 사용하면 NaN과 NaN을 같다고 평가되어 중복추가 불가능
- +0과 -0 같다고 평가되어 중복추가 불가능
- 객체나 배열과 같이 자바스크립트의 모든 값을 요소로 저장가능
const set = new Set();
console.log(set);
set.add(1).add(2)
console.log(set)
set.add(1).add(2).add(2)
console.log(set)
const set2 = new Set();
console.log(NaN === NaN);
console.log(0 === -0);
set2.add(NaN).add(NaN);
console.log(set2);
set2.add(0).add(-0);
console.log(set2);
const set3 = new Set();
set3
.add(1)
.add('a')
.add(true)
.add(undefined)
.add(null)
.add({})
.add([])
.add(() => {});
console.log(set3);
요소 존재 여부 확인
- 특정요소 존재 여부 확인 시 Set.prototype.has 메서드 사용
const set = new Set([1, 2, 3]);
console.log(set.has(2));
console.log(set.has(4));
요소 삭제
- 특정요소를 삭제하려면 Set.prototype.delete 메서드 사용 (성공여부 불리언 값을 반환)
- 인덱스가 아닌 삭제하려는 요소값을 인수로 전달 -> 순서에 의미가 없음, 인덱트x
- 성공 여부를 불리언 값을 반환 -> 연속적 호출 불가능(method chaining)
const set = new Set([1, 2, 3]);
set.delete(2);
console.log(set);
set.delete(1);
console.log(set);
set.delete(0);
console.log(set);
set.delete(1).delete(2);
요소 일괄 삭제
- 객체의 모든 요소를 일괄 삭제 Set.prototype.clear 메서드 사용
- clear 메서드는 언제나 undefined를 반환
const set = new Set([1, 2, 3]);
set.clear();
console.log(set);
요소 순회
- 객체의 요소를 순회하려면 Set.prototype.forEach 메서드를 사용
- Set 객체는 순서에 의미가 없어 인덱스x
- Set 객체는 이터러블 -> for...of 문으로 순회 가능, 스프레드 문법과 배열 디스트럭처링의 대상
인수 | 값 |
---|
첫번째 | 현재 순회 중인 요소값 |
두번째 | 현재 순회 중인 요소값 |
세번째 | 현재 순회 중인 Set 객체 자체 |
const set = new Set([1, 2, 3]);
set.forEach((v, v2, set) => console.log(v, v2, set));
const set = new Set([1, 2, 3]);
console.log(Symbol.iterator in set);
for (const value of set) {
console.log(value);
}
console.log([...set]);
const [a, ...rest] = set;
console.log(a, rest);
집합 연산
- Set 객체를 통해 교집합, 합집합, 차집합 등을 구현 가능
Set.prototype.intersection = function (set) {
return new Set([...this].filter(v => set.has(v)));
}
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);
console.log(setA.intersection(setB));
console.log(setB.intersection(setA));
Set.prototype.union = function (set) {
return new Set([...this, ...set]);
}
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);
console.log(setA.union(setB));
console.log(setB.union(setA));
Set.prototype.difference = function (set) {
return new Set([...this].filter(v => !set.has(v)));
}
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);
console.log(setA.difference(setB));
console.log(setB.difference(setA));
Set.prototype.isSuperset = function (subset) {
const supersetArr = [...this];
return [...subset].every(v => supersetArr.includes(v));
}
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 4]);
console.log(setA.isSuperset(setB));
console.log(setB.isSuperset(setA));
Map
- 키와 값의 쌍으로 이루어진 컬렉션, 객체와 유사
- 인수로 전달되는 이터러블은 키와 값의 쌍으로 이루어진 요소로 구성되어야 함
- 중복된 키를 갖는 요소가 존재하면 덮어씀 -> 중복 키를 갖는 요소 불가능
구분 | 객체 | Map 객체 |
---|
키로 사용할 수 있는 값 | 문자열 또는 심벌 값 | 객체를 포함한 모든 값 |
이터러블 | X | O |
요소 개수 | Object.keys(obj).length | map.size |
Map 객체 생성
const map = new Map();
console.log(map);
const map1 = new Map([['key1', 'value1'], ['key2', 'value2']]);
console.log(map1);
const map2 = new Map([1, 2]);
const map = new Map([['key1', 'value1'], ['key1', 'value2']]);
console.log(map);
요소 개수 확인
- Map.prototype.size 프로퍼티 사용
- setter 함수 없이 getter 함수만 존재하는 접근자 프로퍼티 -> 숫자를 할당하여 Map 요소 개수 변경 불가
console.log(size);
const map = new Map([['key1', 'value1'], ['key2', 'value2']]);
map.size = 10;
console.log(map.size);
요소 추가
- Map.prototype.set 메서드 사용
- 연속적 호출(method chaining)가능
- 일치 비교 연산자(===)을 사용하면 NaN과 NaN를 같다고 평가하여 중복 추가 불가능
- +0과 -0를 같다고 평가하여 중복 추가 불가능
- 키 타입에 제한이 없음 -> 객체를 포함한 모든 값을 키로 사용 가능
const map = new Map();
map
.set('key1', 'value1')
.set('key2', 'value2');
.set('key2', 'value3');
console.log(map);
const map = new Map();
map.set(NaN, 'value1').set(NaN, 'value2');
console.log(map);
map.set(0, 'value1').set(-0, 'value2');
console.log(map);
const map = new Map();
const lee = { name : 'Lee' };
const kim = { name : 'Kim' };
map
.set(lee, 'developer')
.set(kim, 'designer');
console.log(map);
요소 취득
- Map.prototype.get 메서드 사용
- Map 객체에서 인수로 전달한 키를 갖는 요소가 존재하지 않으면 undefined를 반환
const map = new Map();
const lee = { name : 'Lee' };
const kim = { name : 'Kim' };
map
.set(lee, 'developer')
.set(kim, 'designer');
console.log(map.get(lee));
console.log(map.get('key'));
요소 존재 여부 확인
- Map.prototype.has 메서드 사용
- 특정 요소의 존재 여부를 나타내는 불리언 값을 반환
const lee = { name : 'Lee' };
const kim = { name : 'Kim' };
const map = new Map([[lee, 'developer'], [kim, 'designer']]);
console.log(map.has(lee));
console.log(map.has('key'));
요소 삭제
- Map.prototype.delete 메서드 사용
- 삭제 성공 여부를 나타내는 불리언 값을 반환
- 존재하지 않는 키로 Map 객체의 요소를 삭제하면 에러 없이 무시
- set 메서드와 달리 연속적으로 호출 불가능
const lee = { name : 'Lee' };
const kim = { name : 'Kim' };
const map = new Map([[lee, 'developer'], [kim, 'designer']]);
map.delete(lee).delete(kim);
map.delete(kim);
map.delete('key2');
console.log(map);
요소 일괄 삭제
- Map.prototype.clear 메서드 사용
const lee = { name : 'Lee' };
const kim = { name : 'Kim' };
const map = new Map([[lee, 'developer'], [kim, 'designer']]);
map.clear();
console.log(map);
요소 순회
- 객체의 요소를 순회하려면 Map.prototype.forEach 메서드를 사용
- Map 객체는 이터러블 -> for...of 문으로 순회 가능, 스프레드 문법과 배열 디스트럭처링의 대상
- Map 객체는 요소의 순서에 의미를 갖지 않지만 Map 객체를 순회하는 순서는 요소가 추가된 순서를 따름 (이터러블의 순회와 호환성 유지)
인수 | 값 |
---|
첫번째 | 현재 순회 중인 요소값 |
두번째 | 현재 순회 중인 요소값 |
세번째 | 현재 순회 중인 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));
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };
const map =new Map([[lee, 'developer'], [kim, 'designer']]);
for (const entry of map) {
console.log(entry);
}
console.log([...map]);
const [a, b] = map;
console.log(a, b);
Map 메서드 | 설명 |
---|
Map.prototype.keys | Map 객체에서 요소키를 값으로 갖는 이터러블, 이터레이터인 객체 반환 |
Map.prototype.values | Map 객체에서 요소값을 값으로 갖는 이터러블, 이터레이터인 객체 반환 |
Map.prototype.entries | Map 객체에서 요소키와 요소값를 값으로 갖는 이터러블, 이터레이터인 객체 반환 |
const lee = { name: 'Lee' };
const kim = { name: 'Kim' };
const map =new Map([[lee, 'developer'], [kim, 'designer']]);
for (const key of map.keys()){
console.log(key);
}
for (const value of map.values()) {
console.log(value);
}
for (const entry of map.entries()) {
console.log(value);
}
📖 참고도서 : 모던 자바스크립트 Deep Dive 자바스크립트의 기본 개념과 동작 원리 / 이웅모 저 | 위키북스