Map
ES6 이전에는 키와 값을연결하려면 객체를 사용해야 했습니다. 하지만 객체를 이런 목적으로 사용하면 여러가지 단점이 생깁니다.
- 프로토타입 체인 때문에 의도하지 않은 연결이 생길 수 있습니다.
- 객체 안에 연결된 키와 값이 몇 개나 되는지 쉽게 알아낼 수 있는 방법이 없습니다.
- 키는 반드시 문자열이나 심볼이어야 하므로 객체를 키로 써서 값과 연결할 수 없습니다.
- 객체는 프로퍼티 순서를 전혀 보장하지 않습니다.
Map 객체는 이들 결함을 모두 해결했고, 키와 값을 연결할 목적이라면 (문자열만 키로 쓴다 해도) 객체보다 나은 선택입니다. 예를 들어 사용자 객체가 여럿 있고 이들에게 각각 역할을 부여한다고 합시다.
const u1 = {name:'Kim'};
const u2 = {name:'Lee'};
const u3 = {name:'Park'};
const u4 = {name:'Kang'};
먼저 Map을 만듭니다.
const userRoles = new Map();
다음에는 Map의 set() 메서드를 써서 사용자 역할을 할당합니다.
userRoles.set(u1, 'User');
userRoles.set(u2, 'User');
userRoles.set(u3, 'Admin');
set() 메서드는 체인으로 연결할 수 있어서 타이핑하는 수고를 덜어 줍니다.
userRoles
.set(u1, 'User')
.set(u2, 'User')
.set(u3, 'Admin')
생성자에 배열의 배열을 넘기는 형태로 써도 됩니다.
const userRoles = new Map([
[u1, 'User'],
[u2, 'User'],
[u3, 'Admin'],
]);
이제 u2의 역할을 알아볼 때는 get() 메서드를 쓰면 됩니다.
userRoles.get(u2); //'User'
맵에 존재하지 않는 키에 get을 호출하면 undefined를 반환합니다. 맵에 키가 존재하는지 확인하는 has() 메서드도 있습니다.
userRoles.has(u1); // true
userRoles.get(u1); // 'User'
userRoles.has(u4); // false
userRoles.get(u4); // undefined
맵에 이미 존재하는 키에 set()을 호출하면 값이 교체됩니다.
userRoles.get(u1); // 'User'
userRoles.set(u1, 'Admin');
userRoles.get(u1); // 'Admin'
size 프로퍼티는 맵의 요소 숫자를 반환합니다.
userRoles.size; //3
keys() 메서드는 Map의 키를, values() 메서드는 값을, entries() 메서드는 첫 번째 요소가 키이고 두 번째 요소가 값인 배열을 각각 반환합니다. 이들 메서드가 반환하는 것은 모두 이터러블 객체이므로 for…of 루프를 쓸 수 있습니다.
for(let u of userRoles.keys()) {
console.log(u.name);
}
/*
Kim
Lee
Park
*/
for(let r of userRoles.values()) {
console.log(r);
}
/*
User
User
Admin
*/
// 맵도 분해(destruct)할 수 있습니다.
// 분해하면 좀 더 자연스러운 코드가 됩니다.
for(let [u, r] of userRoles.entries()) {
console.log(`${u.name} : ${r}`);
}
/*
Kim : User
Lee : User
Park : Admin
*/
// entries() 메서드는 맵의 기본 이터레이터입니다.
// 위 코드는 다음과 같이 단축해서 쓸 수 있습니다.
for(let [u, r] of userRoles) {
console.log(`${u.name} : ${r}`);
}
/*
Kim : User
Lee : User
Park : Admin
*/
이터러블 객체보다 배열이 필요하다면 확산 연산자spread operator를 쓰면 됩니다.
[...userRoles.values()]; //[ 'User', 'User', 'Admin' ]
Map의 요소를 지울 때는 delete() 메서드를 사용합니다.
userRoles.delete(u2);
userRoles.size; //2
Map의 요소를 모두 지울 때는 clear() 메서드를 사용합니다.
userRoles.clear();
userRoles.size; //0