Frontend/Javascript

[Javascript] Object vs. Map

돌잡이개발자 2022. 4. 16. 01:38

Map

Map은 key-value 쌍을 보유하고 키의 원래 삽입 순서를 기억한다. 어떠한 값이든 key 값으로 사용할 수 있다.

const map1 = new Map();

map1.set('a', 1);
map1.set('b', 2);
map1.set('c', 3);

console.log(map1.get('a'));
// expected output: 1

map1.set('a', 97);

console.log(map1.get('a'));
// expected output: 97

console.log(map1.size);
// expected output: 3

map1.delete('b');

console.log(map1.size);
// expected output: 2

 

Map은 삽입 순서로 요소를 반복한다 . for...of 루프는 각 반복에 대해 [key, value]의 배열을 반환한다.

const iterable = new Map([['a', 1], ['b', 2], ['c', 3]]);

for (const entry of iterable) {
  console.log(entry);
}
// ['a', 1]
// ['b', 2]
// ['c', 3]

for (const [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3

 

Objects vs. Maps

Object와 Map은 유사한 면이 많다. 둘 다 Map키를 값으로 설정하고, 해당 값을 검색하고, 키를 삭제하고, 키에 무언가가 저장되어 있는지 여부를 감지할 수 있다. 자바스크립트에서는 Map이 Object에 비해 많은 이점을 가지고 있다. 아래에서 살펴보자.

 

Key 타입

Map의 key는 number, function, object 등 어떤 타입이든 가능하다. Object의 key는 String이나 Symbol이어야 한다.

const map = new Map();
const myFunction = () => console.log('I am a useful function.');
const myNumber = 666;
const myObject = {
  name: 'plainObjectValue',
  otherKey: 'otherValue'
};
map.set(myFunction, 'function as a key');
map.set(myNumber, 'number as a key');
map.set(myObject, 'object as a key');

console.log(map.get(myFunction)); // function as a key
console.log(map.get(myNumber)); // number as a key
console.log(map.get(myObject)); // object as a key

 

Key 순서

Map은 삽입한 순서대로 key가 정렬되어 있다. Map을 iterate할 경우 삽입된 순서대로 나온다. Object의 key들은 현재는 순서대로 정렬되기는 하지만, 해당 순서들은 항상 보장되는 것은 아니며 Object property 순서에 의존하지 않는 것이 좋다.

 

Size

Map의 크기를 size로 확인할 수 있으며 이는 O(1) 시간 복잡도를 갖는다. Object의 경우 length로 확인해야 하면 이는 O(n) 시간 복잡도가 소요된다.

const map = new Map();
map.set('someKey1', 1);
map.set('someKey2', 1);
...
map.set('someKey100', 1);

console.log(map.size) // 100, Runtime: O(1)

const plainObjMap = {};
plainObjMap['someKey1'] = 1;
plainObjMap['someKey2'] = 1;
...
plainObjMap['someKey100'] = 1;

console.log(Object.keys(plainObjMap).length) // 100, Runtime: O(n)

 

반복문

Map은 Iterable 객체이므로 for...of 반복문을 쉽게 쓸 수 있다. Object는 반복 프로토콜을 구현하거나 Object.keys 또는 Object.entries를 사용하여 객체에 대한 이터러블을 얻을 수 있다.

const map = new Map();
map.set('someKey1', 1);
map.set('someKey2', 2);
map.set('someKey3', 3);

for (let [key, value] of map) {
  console.log(`${key} = ${value}`);
}
// someKey1 = 1
// someKey2 = 2
// someKey3 = 3

const plainObjMap = {};
plainObjMap['someKey1'] = 1;
plainObjMap['someKey2'] = 2;
plainObjMap['someKey3'] = 3;

for (let key of Object.keys(plainObjMap)) {
  const value = plainObjMap[key];
  console.log(`${key} = ${value}`);
}
// someKey1 = 1
// someKey2 = 2
// someKey3 = 3

 

성능

Map은 설계단계부터 데이터의 추가와 제거에 최적화 되어 있기 때문에 성능에 있어서 매우 유리하다.

 

직렬화와 파싱 

Map은 JSON.stringify() 및 JSON.parse()를 지원하지 않는다. How do you JSON.stringify an ES6 Map?

Object는 JSON.stringify() 및 JSON.parse()를 지원한다.

 

 

참고자료

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

https://betterprogramming.pub/stop-using-objects-as-hash-maps-in-javascript-9a272e85f6a8

반응형