Set
- Set 객체는 중복되지 않는 유일한 값들의 집합
- Set 객체는 배열과 유사하지만 다음과 같은 차이가 있음
- Set 객체는 수학적 집합을 구현하기 위한 자료구조
| 구분 | 배열 | Set 객체 |
| 동일한 값 중복 포함 | O | X |
| 요소 순서에 의미 | O | X |
| 인덱스로 요소 접근 | O | X |
1. Set 객체의 생성
- 생성자 함수로 생성하며 인수를 전달하지 않으면 빈 Set 객체 생성
- 이터러블을 인수로 전달받아 Set 객체를 생성하는데 이터러블의 중복된 값은 Set 객체에 요소로 저장되지 않음 (중복 제거 가능)
const set = new Set();
console.log(set); // Set(0){}
const uniq = array => [...new Set(array)];
console.log(uniq([2, 1, 2, 3, 4, 3, 4])); // [2, 1, 3, 4]
2. 요소 개수 확인
- Set.prototype.size 프로퍼티 사용
- size 프로퍼티는 getter 함수만 존재하는 접근자 프로퍼티로 size에 숫자를 할당하여 Set 객체의 요소 개수 변경 불가능
const set = new Set([1, 2, 3]);
console.log(set.size); // 3
3. 요소 추가
- Set.prototype.add 메서드 사용
- add 메서드는 새로운 요소가 추가된 Set 객체를 반환하기 때문에 연속적으로 호출 가능
- NaN 과 NaN, +0 과 -0을 같다고 평가하여 중복 추가 불가
- 객체나 배열같이 자바스크립트의 모든 값을 요소로 저장 가능
const set = new Set();
set.add(1);
console.log(set); // Set(1){1}
set.add(2).add(3);
console.log(set); // Set(3){1, 2, 3}
set.add(NaN).add(NaN).add(+0).add(-0);
console.log(set); // Set(5){1, 2, 3, NaN, 0}
4. 요소 존재 여부 확인
- Set.prototype.has 메서드 사용
- 특정 요소의 존재 여부를 나타내는 불리언 값 반환
const set = new Set([1, 2, 3]);
console.log(set.has(4000000)); // false
5. 요소 삭제
- Set.prototype.delete 메서드 사용
- 삭제 성공 여부를 나타내는 불리언 값 반환 (연속 호출 불가)
- Set 객체는 배열과 같이 인덱스를 갖지 않기 때문에 delete 메서드에 인덱스가 아니라 요소 값을 인수로 전달해야 함
const set = new Set([1, 2, 3]);
set.delete(2);
console.log(set); // Set(2){1, 3}
6. 요소 일괄 삭제
- Set.prototype.clear 메서드 사용
- 언제나 undefined 반환
const set = new Set([1, 2, 3]);
set.clear();
console.log(set); // Set(0){}
7. 요소 순회
- Set.prototype.forEach 메서드 사용
- 첫 번째 인수 : 현재 순회 중인 요소 값
- 두 번째 인수 : 현재 순회 중인 요소 값
- 세 번째 인수 : 현재 순회 중인 Set 객체 자체
const set = new Set([1, 2, 3]);
set.forEach((v1, v2, set)=> console.log(v1, v2, set));
/*
1 1 Set(3) {1, 2, 3}
2 2 Set(3) {1, 2, 3}
3 3 Set(3) {1, 2, 3}
*/
// Set 객체는 Set.prototype 의 Symbol.iterator 메서드를 상속받는 이터러블
console.log(Symbol.iterator in set); // true
// 이터러블인 Set 객체는 for ... of 문으로 순회 가능
for(const value of set){
console.log(value); // 1 2 3
}
// 이터러블인 Set객체는 스프레드 문법의 대상이 될 수 있다
console.log([...set]); [1, 2, 3]
// 이터러블인 Set 객체는 배열 디스트럭처링 할당의 대상이 될 수 있다
const [a, ... rest] = set;
console.log(a, rest); // 1, [2, 3]
8. 집합 연산
8-1. 교집합
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)); // Set(2){2, 4}
8-2. 합집합
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)); // Set(4){1, 2, 3, 4}
8-3. 차집합
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)); // Set(2){1, 3}
console.log(setB.difference(setA)); // Set(0){}
8-4. 부분 집합과 상위 집합
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)); // true
console.log(setB.isSuperset(setA)); // false
Map
- Map 객체는 키와 값의 쌍으로 이루어진 컬렉션
- Map 객체는 객체와 유사하지만 다음과 같은 차이가 있음
| 구분 | 객체 | Map 객체 |
| 키로 사용할 수 있는 값 | 문자열 또는 심벌 값 | 객체를 포함한 모든 값 |
| 이터러블 | X | O |
| 요소 개수 확인 | Object.keys(obj).length | map.size |
1. Map 객체의 생성
- Map 객체는 Map 생성자 함수로 생성
- Map 생성자 함수에 인수를 전달하지 않으면 빈 Map 객체 생성
- Map 생성자 함수는 이터러블을 인수로 전달받아 Map 객체 생성 (이때 인수로 전달되는 이터러블은 키와 값의 쌍으로 이루어진 요소로 구성 되어야 함)
- 인수에 중복된 키를 갖는 요소가 존재하면 값이 덮어써지기 때문에 중복된 키를 갖는 요소 존재 불가능
const map = new Map();
console.log(map); // Map(0){}
const map1 = new Map([['key1', 'val1'], ['key2', 'val2'],['key1', 'val1']]);
console.log(map1); // Map(2) {'key1' => 'val1', 'key2' => 'val2'}
2. 요소 개수 확인
- Map.prototype.size 프로퍼티 사용
- getter 함수만 존재하는 접근자 프로퍼티로 size 프로퍼티에 숫자를 할당하여 요소 개수 변경 불가능
const map = new Map([['key1', 'val1'], ['key2', 'val2']]);
console.log(map.size); // 2
3. 요소 추가
- Map.prototype.set 메서드 사용
- set 메서드는 새로운 요소가 추가된 Map 객체를 반환하기 때문에 set 메서드 연속 호출 가능
- 중복된 키를 갖는 요소를 추가하면 값이 덮어써짐
- NaN과 NaN, +0 과 -0을 같다고 평가하여 중복 추가 불가
const map = new Map();
map.set('key1', 'val1').set('key1', 'val2').set('key2', 'val2')
console.log(map); // Map(2) {'key1' => 'val2', 'key2' => 'val2'}
map.set(NaN, 'val3').set(NaN, 'val4').set(0, 'val4').set(-0, 'val5');
console.log(map); // Map(4) {'key1' => 'val2', 'key2' => 'val2', NaN => 'val4', 0 => 'val5'}
- 심벌 값과 문자열만 허용하는 객체와 다르게 Map 객체에는 객체를 포함한 모든 값을 키로 사용 가능
const map = new Map();
const echichi = { name : 'Echichi' };
const achichi = { name : 'Achichi' };
map.set(echichi, 'developer').set(achichi, 'architect');
/*
Map(2) {{…} => 'developer', {…} => 'architect'}
[[Entries]]
0: {Object => "developer"}
key: {name: 'Echichi'}
value: "developer"
1: {Object => "architect"}
key: {name: 'Achichi'}
value: "architect"
size: 2
*/
4. 요소 취득
- Map.prototype.get 메서드 사용
- get 메서드의 인수로 키를 전달하면 Map 객체에서 인수로 전달한 키를 갖는 값 반환
const map = new Map();
const echichi = { name : 'Echichi' };
const achichi = { name : 'Achichi' };
map.set(echichi, 'developer').set(achichi, 'architect');
console.log(map.get(echichi)); // developer
5. 요소 존재 여부 확인
- Map.prototype.has 메서드 사용
- 특정 요소의 존재 여부를 나타내는 불리언 값 반환
const map = new Map();
const echichi = { name : 'Echichi' };
const achichi = { name : 'Achichi' };
map.set(echichi, 'developer').set(achichi, 'architect');
console.log(map.has(echichi)); // true
console.log(map.has(chiyak)); // false
6. 요소 삭제
- Map.prototype.delete 메서드 사용
- 삭제 성공 여부를 나타내는 불리언 값 반환 (연속 호출 불가)
const map = new Map();
const echichi = { name : 'Echichi' };
const achichi = { name : 'Achichi' };
map.set(echichi, 'developer').set(achichi, 'architect');
map.delete(echichi);
console.log(map); // Map(1){ { name : 'Achichi' } => 'architect' }
7. 요소 일괄 삭제
- Map.prototype.clear 메서드 사용
const map = new Map();
const echichi = { name : 'Echichi' };
const achichi = { name : 'Achichi' };
map.set(echichi, 'developer').set(achichi, 'architect');
map.clear();
console.log(map); // Map(0){}
8. 요소 순회
- Map.prototype.forEach 메서드 사용
- 첫 번째 인수 : 현재 순회 중인 요소값
- 두 번째 인수 : 현재 순회 중인 요소키
- 세 번째 인수 : 현재 순회 중인 Map 객체 자체
const map = new Map();
const echichi = { name : 'Echichi' };
const achichi = { name : 'Achichi' };
map.set(echichi, 'developer').set(achichi, 'architect');
map.forEach((v, k, map)=> console.log(v, k, map));
/*
developer {name: 'Echichi'} Map(2) {{…} => 'developer', {…} => 'architect'}
architect {name: 'Achichi'} Map(2) {{…} => 'developer', {…} => 'architect'}
*/
// Map 객체는 Map.prototype 의 Symbol.iterator 메서드를 상속받는 이터러블
console.log(Symbol.iterator in map); // true
// 이터러블인 Map 객체는 for ... of 문으로 순회 가능
for(const entry of map){
console.log(entry); // (2) [{…}, 'developer'] [{…}, 'architect']
}
// 이터러블인 Map 스프레드 문법의 대상이 될 수 있다
console.log([...map]); [[{name: 'Echichi'}, "developer"],[{name: 'Achichi'}, "architect"]]
// 이터러블인 Map 객체는 배열 디스트럭처링 할당의 대상이 될 수 있다
const [a, b] = map;
console.log(a, b); // [[{name: 'Echichi'}, "developer"],[{name: 'Achichi'}, "architect"]]
| Map 메서드 | 설명 |
| Map.prototype.keys | Map 객체에서 요소키를 값으로 갖는 이터러블이면서 동시에 이터레이터인 객체 반환 |
| Map.prototype.values | Map 객체에서 요소값을 값으로 갖는 이터러블이면서 동시에 이터레이터인 객체 반환 |
| Map.prototype.entries | Map 객체에서 요소키와 요소값을 값으로 갖는 이터러블이면서 동시에 이터레이터인 객체 반환 |
const map = new Map();
const echichi = { name : 'Echichi' };
const achichi = { name : 'Achichi' };
map.set(echichi, 'developer').set(achichi, 'architect');
for (const key of map.keys()) {
console.log(key); // {name: 'Echichi'} {name: 'Achichi'}
}
for (const value of map.values()) {
console.log(value); // developer architect
}
for (const entry of map.entries()) {
console.log(entry); // [{name: 'Echichi'}, developer] [{name: 'Achichi'}, architect]
}'Javascript' 카테고리의 다른 글
| [모던 자바스크립트 Deep Dive] 36-1. DOM (1) | 2023.12.01 |
|---|---|
| [모던 자바스크립트 Deep Dive] 35. 브라우저의 렌더링 과정 (1) | 2023.11.29 |
| [모던 자바스크립트 Deep Dive] 33. 디스트럭처링 할당 (1) | 2023.11.28 |
| [모던 자바스크립트 Deep Dive] 32. 스프레드 문법 (0) | 2023.11.28 |
| [모던 자바스크립트 Deep Dive] 31. 이터러블 (1) | 2023.11.27 |