분류 javascript

JavaScript로 작성된 Map 80/20 안내서

컨텐츠 정보

  • 조회 201 (작성일 )

본문

JavaScript에서 Map은 키/값 쌍을 저장하는 객체입니다. Map는 일반적인 자바스크립트 객체와 비슷하지만 객체와 Map간에 유용한 몇 가지 주요 차이점이 있습니다.


http://thecodebarbarian.com/the-80-20-guide-to-maps-in-javascript.html 


Maps vs Objects 


일부 키/값 경로를 저장하는 JavaScript 객체를 생성한다고 가정합니다. 아래와 같이 일반 오래된 JavaScript 객체 또는 "POJO"를 간단히 정의 할 수 있습니다.


const obj = {
  name: 'Jean-Luc Picard',
  age: 59,
  rank: 'Captain'
};

obj.name; // 'Jean-Luc Picard'

아래에 표시된 것과 동일한 키와 값을 포함하는 맵을 정의 할 수도 있습니다.


const map = new Map([
  // You define a map via an array of 2-element arrays. The first
  // element of each nested array is the key, and the 2nd is the value
  ['name', 'Jean-Luc Picard'],
  ['age', 59],
  ['rank', 'Captain']
]);

// To get the value associated with a given `key` in a map, you
// need to call `map.get(key)`. Using `map.key` will **not** work.
map.get('name'); // 'Jean-Luc Picard'

피카드 선장의 나이를 원한다고 가정 해 봅시다. 객체와 함께 obj.age를 사용할 수 있습니다. 지도에서는 ​​map.get ( 'age')를 사용합니다. 내장 JavaScript 기능과 충돌하지 않는 속성에는 적합하지만 객체의 생성자 속성을 얻으려면 어떻습니까? 이 경우 obj.constructor가 정의되지만 map.get ( 'constructor')는 정의되지 않습니다.


obj.constructor; // [Function: Object]
map.get('constructor'); // undefined

Maps에는 상속에 대한 개념이 없습니다. Maps에는 상속 된 키가 없습니다. 따라서 기존 방법 및 속성과 충돌하는 데이터에 대해 걱정할 필요 없이 원시 데이터를 저장하는 데 이상적입니다. 예를 들어, Maps는 프로토 타입 오염에 영향을 받지 않습니다. 사용자 데이터를 순식간에 복사하면 악의적인 사용자가 클래스 메서드를 덮어 쓸 수 있는 보안 취약점이 있습니다.


또 다른 주요 차이점은 맵을 사용하면 문자열 뿐만 아니라 객체 키를 저장할 수 있다는 것입니다. 날짜 또는 숫자와 같은 객체를 키로 저장할 때 약간의 혼란이 발생할 수 있습니다.


const map = new Map([]);

const n1 = new Number(5);
const n2 = new Number(5);

map.set(n1, 'One');
map.set(n2, 'Two');

// `n1` and `n2` are objects, so `n1 !== n2`. That means the map has
// separate keys for `n1` and `n2`.
map.get(n1); // 'One'
map.get(n2); // 'Two'
map.get(5); // undefined

// If you were to do this with an object, `n2` would overwrite `n1`
const obj = {};
obj[n1] = 'One';
obj[n2] = 'Two';

obj[n1]; // 'Two'
obj[5]; // 'Two'

Maps에는 Maps의 키/값 쌍 수를 반환하는 size 속성도 있습니다. 객체의 키 수를 얻으려면 Object.keys(obj) .length를 수행해야 합니다.


map.size; // 3

또 다른 차이점은 맵의 키 순서가 보장된다는 것입니다. 즉, map.keys()를 호출하면 항상 키가 맵에 추가 된 순서대로 가져옵니다. Captain Picard 예에서 map.keys()는 항상 이름, 나이 및 순위를 순서대로 반환합니다.


ES6 호환 브라우저에서도 객체 키 순서가 보장됩니다. 예를 들어 Object.keys(obj)는 ES6 호환 JavaScript 런타임에서 항상 [ 'name', 'age', 'rank']를 반환합니다. 그러나 이전 런타임 (Internet Explorer 등)에서는 Object.keys(obj)가 다른 순서로 키를 반환 할 수 있습니다.


Map#keys(), Map#values(), Map#entries() 


Maps에는 Maps를 반복하는 세 가지 기본 메소드인 keys(), values​​() 및 entries()가 있습니다. Object.keys()와 달리 Map#keys() 함수는 배열이 아닌 iterator를 반환합니다. 즉, Maps의 키를 반복하는 가장 쉬운 방법은 for/of  loop를 사용하는 것입니다.


const map = new Map([
  ['name', 'Jean-Luc Picard'],
  ['age', 59],
  ['rank', 'Captain']
]);

const iterator = map.keys();
console.log(iterator); // MapIterator { 'name', 'age', 'rank' }

// `map.keys()` returns an iterator, not an array, so you can't
// access the values using `[]`
iterator[0]; // undefined

// The `for/of` loop can loop through iterators
for (const key of map.keys()) {
  key; // 'name', 'age', 'rank'
}

때로는 iterator를 배열로 변환하는 것이 편리하므로 filter() 및 map()과 같은 배열 메서드를 사용할 수 있습니다. iterator를 배열로 변환하는 가장 쉬운 방법은 내장 Array.from() 함수를 사용하는 것입니다.


const arr = Array.from(map.keys());

arr.length; // 3
arr[0]; // 'name'
arr[1]; // 'age'
arr[2]; // 'rank'

Map#values​​() 함수는 iterator를 반환합니다. iterator는 맵의 값을 반복합니다.


for (const v of map.values()) {
  v; // 'Jean-Luc Picard', 59, 'Captain'
}

마지막으로 Map # entries()는 Map 생성자와 비슷한 형식으로 맵의 키/값 쌍을 반복하는 iterator를 반환합니다. Map#entries() 함수는 Map 클래스와 Object.entries()에 해당합니다.


for (const [key, value] of map.entries()) {
  key; // 'name', 'age', 'rank'
  value; // 'Jean-Luc Picard', 59, 'Captain'
}

Map#entries() 함수를 사용하면 map를 쉽게 복사 할 수 있습니다. map를 복제하는 것은 map.entries()를 배열로 변환하는 것만큼 간단합니다.


// `clone` is now a separate map that contains the same keys/values
// as `map`.
const clone = new Map(Array.from(map.entries()));

계속 


JavaScript 개발자는 일반적으로 객체를 사용하여 사용자 데이터를 저장하지만 Maps에는 몇 가지 장점이 있습니다. 프로토 타입 오염 또는 JSON 데이터 덮어 쓰기 클래스 메소드의 위험이 없습니다. Maps을 사용하면 객체 키를 저장할 수 있습니다. 이는 symbol을 설정하지 않고 데이터를 객체와 연결하려는 경우 유용 할 수 있습니다. 오픈 소스 JavaScript에서는 Maps이 여전히 흔하지 않습니다. 내가 본 유일한 사용 사례는 몽구스의 Maps 유형입니다. 그러나 Maps은 프로토 타입 오염의 위험을 피하기 때문에 JSON 데이터를 표현하기 위해 실험 해 볼 가치가 있습니다.