맵은 키와 값을 연결한다는 점에서 객체와 비슷하고, 셋은 중복을 허용하지 않는다는 점을 제외하면 배열과 비슷
MAP
ES6이전에는 키와 값을 연결하려면 객체를 사용해야 했음. 하지만 객체를 이런 목적으로 사용하면 여러가지 단점이 생김
- 프로토타입 체인 때문에 의도하지 않은 연결이 생길 수 있음
- 객체 안 연결된 키와 값이 몇 개나 되는지 쉽게 알아낼 방법이 없음
- 키는 반드시 문자열이나 심볼이어야 하므로 객체를 키로 써서 값과 연결할 수 없음
- 객체는 프로퍼티 순서를 전혀 보장하지 않음
map은 키와 값을 연결할 목적이라면 객체보다 나은 선택
1 2 3 4
| const n1 = {name:'shin'}; const n2 = {name:'jane'}; const n3 = {name:'jin'}; const n4 = {name:'tt'};
|
map
먼저 맵을 만듭니다.
1
| const userRoles = new Map();
|
set()
다음에는 맵의 set()
메서드를 써서 사용자의 역할을 할당
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| userRoles.set(u1, 'user'); userRoles.set(u2, 'user'); userRoles.set(u3, 'admin'); userRoles .set(u1, 'user') .set(u2, 'user') .set(u3, 'admin'); const userRoles = new Map([ [u1, 'user'], [u2, 'user'], [u3, 'admin'], ]);
|
get()
이제 u2의 역할을 알아볼 때는 get()
메서드를 쓰면 됨.
맵에 존재하지 않는 키에 get을 호출하면 undefined
를 반환.
has()
맵에 키가 존재하는지 확인하는 has()
메서드
1 2 3 4
| userRoles.has(u1); userRoles.get(u1); userRoles.has(u4); userRoles.get(u4);
|
맵에 이미 존재하는 키에 set()을 호출하면 값이 교체됨
1 2 3
| userRoles.get(u1); userRoles.set(u1, 'admin'); userRoles.get(u1);
|
size()
size프로퍼티는 맵의 요소 갯수를 반환
keys(),values(), entries()
key메서드는 맵의 키,
values 메서드는 값,
entries 메서드는 첫번째 요소가 키값이고 두번째 요소가 값인 배열을 반환
이 메서드가 반환하는 것은 모두 이터러블 객체여서 for...of루프를 쓸 수 있음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| for(let u of userRoles.keys()) console.log(u.name); for(let r of userRoles.values()) console.log(r); for(let ur of userRoles.entries()) console.log(`${ur[0].name}: ${ur[1]}`); for(let [u, r] of userRoles.entries()) console.log(`${u.name}: ${r}`); for(let [u, r] of userRoles) console.log(`${u.name}: ${r}`);
|
이터러블 객체보다 배열이 필요하다면 확산 연산자를 쓰면 됨
1
| [...userRoles.values()];
|
delete()
맵의 요소를 지울 떄 사용
1 2
| userRoles.delete(u2); userRoles.size;
|
clear()
맵의 요소를 모두 지울 때 사용
1 2
| userRoles.clear(); userRoles.size;
|
위크맵
WeakMap은 다음 차이점을 제외하면 Map과 완전히 같음
- 키는 반드시 객체여야 한다.
- WeakMap의 키는 가비지 콜렉션에 포함될 수 있다.
- WeakMap은 이터러블이 아니며 clear()메서드도 없음
일반적으로 자바스크립트 코드는 코드 어딘가에서 객체를 참고하는 한 객체의 메모리를 계속 유지하려고 하는데 WeakMap은 그렇지 않음. 가비지 콜렉션 중인 객체를 노출할 위험이 큼
WeakMap의 이런 특징은 객체 인스턴스의 전용 키를 저장하기에 알맞음
1 2 3 4 5 6 7 8 9 10 11
| const secretHolder = (function() { const secret = new WeakMap(); return class{ setSecret(secret){ secret.set(this, secret); } getSecret(){ return secret.get(this); } } })();
|
비밀을 저장할 때는 setSecret, 보려고 할 때에는 getSecret
1 2 3 4 5 6 7 8
| const a = new secretHolder(); const b = new secretHolder(); a.setSecret('secret A'); b.setSecret('secret B'); a.getSecret(); b.getSecret();
|
일반적인 Map을 써도 되지만 그렇게 하면 secretHolder 인스턴스에 저장한 내용은 가비지 콜렉션에 포함되지 않음. 가지비 콜렉션에 추가하고 싶으면 WeakMap(?)
Set
Set은 중복을 허용하지 않는 데이터 집합.
같은 사용자에게 같은 역할을 여러번 부여한다는 것은 상식적이지 않음. 셋은 이런 경웨 이상적인 데이터 구조
1 2 3 4 5 6 7 8 9 10
| const roles = new Set(); roles.ass("user"); roles.add("admin"); roles.size;
|
추가하려는 것이 이미 셋에 있는지 확인할 필요 없음. 이미 있다면 아무 일도 일어나지 않음
1 2
| roles.add("user"); roles.size;
|
역할을 제거하고 싶을 떄에는 delete()
제거에 성공했다면(그런 역할이 셋에 존재했다면) true
반환, 아니면 false
1 2 3
| roles.delete("admin"); roles; roles.delete("admin");
|
WeakSet
위크셋은 객체만 포함 할 수 있으며, 이 객체들은 가비지 콜렉터의 대상이 됨.
WeakMap과 마찮가지로 WeakSet도 이터러블이 아님
위크셋의 용도는 매우 적음.
실제 용도는 주어진 객체가 셋 안에 존재하는지 아닌지를 알아보는 것 뿐 이라고 해도 과언이 아님
EX) 산타클로스가 jingjing라는 WeakSet을 가지고 어떤 아이가 우는 아이인지 확인해서 선물대신 석탄(도 가격이 올랐다던데)을 놓고 온다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const jingjing = new WeakSet(); const children = [] {name: "suzy"}, {name: "shin"} ]; jingjing.add(children[1]); for(let child of children){ if(jingjing.has(child)) console.log(`Coal for ${child.name}!`); else console.log(`Presents for ${child.name}!`); }
|