Map: data structure that we can use to map values to keys. map can have any type of key.
Map: 다양한 타입의 값을 키로 사용할 수 있는 데이터 구조
Map은 모든 타입을 키로 가질 수 있다는 점에서 객체와 다르다. 객체는 키를 문자열로밖에 가질 수 없다.
Map을 만드는 방법은 다음과 같다.
const rest = new Map();
rest.set('name','lingling');
rest.set(1, 'Hongkong');
rest.set(2, 'Lisbon');
rest.set('categories',['Italian','Pizzaria','vagetrain'])
.set('open', 11)
.set('close',23)
.set(true,'we are open')
.set(false, 'we are closed')
먼저 빈 Map을 new Map()로 만들어주고 set으로 내용을 넣어준다. Map의 값을 가져오는 방법은 get 메서드를 사용한다.
console.log(rest.get('name'))
console.log(rest.get(true))
console.log(rest.get(1))
Map에서 키의 존재 여부를 확인하거나 키를 삭제하는 방법은 아래와 같다.
console.log(rest.has('categories')); // true
rest.delete(2);
console.log(rest.size); // 5
Map의 키로 배열을 사용할 수도 있지만, 아래 예제와 같이 직접 배열을 사용하면 예상과 다른 결과가 나올 수 있다.
rest.set([1, 2], 'Test');
console.log(rest.get([1,2]))
//undeifned it's not the same object in the heap
위 코드에서 get([1, 2])가 undefined를 반환하는 이유는 배열이 객체이기 때문에 똑같아 보이는 배열도 서로 다른 메모리 주소를 가지기 때문이다.
따라서, 배열을 키로 사용할 때는 변수에 배열을 정의하고 그 변수를 키로 사용해야 한다.
const arr = [1,2]
rest.set(arr,'Test')
console.log(rest)
console.log(rest.size)
// rest.clear()
console.log(rest.get(arr))
이렇게 하면 동일한 배열 객체를 참조하므로 get 메서드가 올바르게 동작하게 된다.
Map을 만들어주는 다른 방법도 있는데 그걸 알아보자. 위에서는 빈 맵을 만들어주고 set으로 그 안을 채운 뒤 get으로 내용을 얻는 것이었는데, 처음부터 Map을 채워서 만들 수 있다. 아래의 코드를 보자.
const question = new Map([
['question',
'What is the best programming language in the world?'],
[1,'C'],
[2,'Java'],
[3,'Javascript'],
['correct',3],
[true, 'Correct'],
[false,'Try again!']
])
console.log(question)
위의 코드를 보면 알 수 있듯이 객체에서 키와 벨류를 모두 루프할 수 있게 해주는 Object.entries와 아주 비슷하게 생겼다. 그래서 객체를 Map 형태로 변환해주는 방법은 아래와 같다.
const hoursMap = new Map(Object.entries(openingHours));
console.log(hoursMap)
객체를 Map으로 변환하는 이유는 객체는 iterable하지 않지만 Map은 iterable하기 때문에 루프해주고 싶을 때 Map으로 변환해주면 편리하다.
다음으로 iterable한 Map을 루프하는 코드를 보자.
console.log(question.get('question'))
for(const [key,value] of question){
if(typeof key === 'number')
console.log(`Answer ${key}: ${value}`)
}
const answer = Number(prompt('Your answer'));
console.log(question.get(question.get('correct') === answer))
question 맵을 for of로 루프한 뒤, key가 number일 때 콘솔에 찍히게 해두었다. 결과는 이렇게 나온다.
Answer 1: C
Answer 2: Java
Answer 3: Javascript
여기에 유저가 답을 적을 수 있게 prompt를 넣어주고, key값 숫자가 일치해야 하므로 Number 형변환을 해준 것이다. 그래서 결과가 correct 값과 같으면 true이므로 question.get으로 'Correct'가 결과로 프린트된다.
Map을 array로 바꾸는건 이렇게 하면 된다.
console.log(([...question]))
console.log(...question.entries())
console.log(...question.keys())
console.log(...question.values())
이렇게 하면 Map을 다양한 형태의 배열로 변환할 수 있다.
마지막으로 언제 Object를 쓰고 언제 Map을 써야 하는지 알아보자.
Object를 사용할 때:
메서드에 함수를 추가해야 할 때
: 객체는 프로토타입을 상속받기 때문에 메서드를 추가하고 상속받은 메서드를 사용할 수 있다.JSON 형식을 사용해야 할 때
: JSON은 객체 표기법을 사용하므로, JSON 데이터와 호환되게 작업할 때는 객체를 사용해야 한다.Map을 사용할 때:
키를 문자열 아닌 다른 타입으로 사용하고 싶을 때
: Map은 모든 타입의 키를 가질 수 있다. 객체는 키를 문자열로만 가질 수 있는 반면, Map은 숫자, 객체, 함수 등 다양한 타입을 키로 사용할 수 있다.순서가 중요한 데이터를 다룰 때
: Map은 삽입된 순서대로 요소를 순회할 수 있다. 이는 객체와 달리 순서가 보장되기 때문에 순서가 중요한 경우 Map을 사용하는 것이 좋다.키의 개수가 많고 빈번한 삽입/삭제가 있는 경우
: Map은 성능 면에서 객체보다 더 나은 성능을 보일 수 있다. 특히, 키의 개수가 많거나 빈번한 삽입과 삭제가 이루어질 때 Map을 사용하는 것이 유리하다.