JavaScript

JavaScript

kimddakki 2022. 6. 3. 16:58

 - 객체 : 키가 있는 컬렉션을 저장함.

 - 배열 : 순서가 있는 컬렉션을 저장함.

 

※ 그러나 현실 세계를 반영하기에 위 두 자료구조만으론 부족하여 맵과 셋이 등장하게 되었씁니다.

 


맵 ( Map )

 - 맵은 키가 있는 데이터를 저장한다는 점에서 객체와 유사합니다. 맵은 키에 다양한 자료형을 허용한다는 점에서 차이가

   있습니다.

new Map() - 맵을 만듭니다.
map.set( key, value ) - key를 이용해 value를 저장합니다.
map.get( key ) - key에 해당하는 값을 반환합니다. key가 존재하지 않으면 undefined를 반환합니다.
map.has( key ) - key가 존재한다면 true, 존재하지 않으면 false를 반환합니다.
map.delete( key ) - key에 해당하는 값을 삭제합니다.
map.clear() - 맵 안의 모든 요소를 제거합니다.
map.size - 요소의 개수를 반환합니다.
let map = new Map();

map.set("1", "str1"); // 문자형 키
map.set(1, "num1"); // 숫자형 키
map.set(true, "bool1"); // 불린형 키

// 객체는 키를 문자형으로 반환한다.
// 맵은 키의 타입을 변환하지 않고 그대로 유지 한다.

console.log(map.get(1)); // num1
console.log(map.get("1")); // str1
console.log(map.size); // 3
console.log(map);
//Map(3) { '1' => 'str1', 1 => 'num1', true => 'bool1' }

 - 맵은 객체와 달리 키를 문자형으로 변환하지 않습니다. 키엔 자료형 제약이 없습니다.

map[key]는 Map을 쓰는 바른 방법이 아닙니다.
map[key] = 2로 값을 설정하는 것 같이 map[key]를 사용할 수 있긴 합니다. 
하지만 이 방법은 map을 일반 객체처럼 취급하게 됩니다. 따라서 여러 제약이 생기게 되죠.

map을 사용할 땐 map전용 메서드 set, get 등을 사용해야만 합니다.

 - 맵은 키로 객체를 허용합니다.

let john = { name: "John" };

// 고객의 가게 방분 횟수를 센다고 가정해보자
let visitsCountMap = new Map();

// john을 맵의 키로 사용
visitsCountMap.set(john, 123);

console.log(visitsCountMap.get(john)); //123
console.log(visitsCountMap);
// Map(1) { { name: 'John' } => 123 }
console.log(john);
// { name: 'John' }

 - 객체를 키로 사용할 수 있다는 점이 맵의 가장 중요한 기능 중 하나입니다.

 - 객체에는 문자열 키를 사용할 수 있습니다. 하지만 객체 키는 사용할 수 없습니다.

 

   객체형 키를 객체에 사용해보자.

let john = { name: "John" };
let kim = { name: "kim" };

let visitsCountObj = {};
visitsCountObj[john] = 123;
visitsCountObj[kim] = 456;

console.log(visitsCountObj);
// { '[object Object]': 123 }

console.log(visitsCountObj["[object Object]"]); // 456

 - visitsCountObj는 객체이기 때문에 모든 키를 문자형으로 변환시킵니다. 이 과정에서 john은 문자형으로 변환되어

   "[object Object]"가 됩니다.

체이닝
map.set을 호출할 때마다 맵 자신이 반환됩니다. 
이를 이용하면 map.set을 '체이닝(chaining)'할 수 있습니다.

map.set('1', 'str1')
  .set(1, 'num1')
  .set(true, 'bool1');

 


맵의 요소에 반복 작업하기

 - 다음 3가지 메서드를 사용하여 맵의 각 요소에 반복 작업을 할 수 있습니다.

map.key() - 각 요소의 키를 모은 반복 가능한 ( Iterable ) 객체를 반환합니다.
map.value() - 각 요소의 값을 모은 이터러블 객체를 반환합니다.
map.entries() - 요소의 [키, 값]을 한 쌍으로 하는 이터러블 객체를 반환합니다.
                이 이터러블 객체는 for .. of 문의 기초로 쓰입니다.
let recipeMap = new Map([
  ["cucumber", 500],
  ["tomatoes", 350],
  ["onion", 50],
]);

// 키 (vegetable) 을 대상으로 순회합니다.
for (let vegetable of recipeMap.keys()) {
  console.log(vegetable);
}
// cucumber, tomatoes, onion

// 값 (amount)를 대상으로 순회합니다.
for (let amout of recipeMap.values()) {
  console.log(amout);
}
// 500 350 50

// [키, 값] 쌍을 대상으로 순회합니다.
for (let entry of recipeMap) {
  console.log(entry);
}
// [ 'cucumber', 500 ] [ 'tomatoes', 350 ] [ 'onion', 50 ]

 - 맵은 삽인 순서를 기억합니다.

   맵은 값이 삽입된 순서드로 순회를 실시합니다. 객체가 프로퍼티 순서를 기억하지 못하는 것과는 다릅니다.

 

 - 더하여 맵은 배열과 유사하게 내장 메서드 forEach 도 지원합니다.

recipeMap.forEach((value, key, map) => {
  console.log(`${key} : ${value}`);
});
// cucumber : 500
// tomatoes : 350
// onion : 50

Object.entries : 객체를 맵으로 바꾸기

 - 각 요소가 키 - 값 쌍인 배열이나 이터러블 객체를 초기화 용도로 맵에 전달해 새로운 맵을 만들 수 있다.

let map = new Map([
  ["1", "str1"],
  [1, "num1"],
  [true, "bool1"],
]);

console.log(map.get("1"));

 - 평범한 객체를 가지고 맵을 만들고 싶다면 내장 메서드 Object.entries(obj)를 활용해야 한다.

   이 메서드는 객체의 키 값 쌍을 요소 ( [ key, value ] )로 가지는 배열을 반환한다.

let obj = {
  name: "john",
  age: 30,
};

console.log(Object.entries(obj));
// [ [ 'name', 'john' ], [ 'age', 30 ] ]
let mapObj = new Map(Object.entries(obj));

console.log(mapObj);
// Map(2) { 'name' => 'john', 'age' => 30 }
console.log(mapObj.get("name"));
// john

 - Object.entries 메서드를 활용해 객체 obj를 배열로 바꾸고 이 배열을 사용해 새로운 맵을 만드는 과정이다!!!

 


Object.fromEntries 맵을 객체로 바꾸기

 - 위에서 Object.entries( obj )를 통해 객체를 맵으로 바꾸는 방법을 알아 보았습니다.

 - 이젠 반대로 맵을 객체로 바꿔 봅시다.

   Object fromEntries 메서드는 각 요소가 [ 키 , 값 ] 쌍인 배열을 객체로 바꿔줍니다.

let prices = Object.fromEntries([
  ["banana", 1],
  ["orange", 2],
  ["meat", 4],
]);

console.log(prices);
// { banana: 1, orange: 2, meat: 4 }
let map = new Map();
map.set("banana", 1);
map.set("orange", 2);
map.set("meat", 4);

console.log(map);
// Map(3) { 'banana' => 1, 'orange' => 2, 'meat' => 4 }

console.log(map.entries());
// [Map Entries] { [ 'banana', 1 ], [ 'orange', 2 ], [ 'meat', 4 ] }
const obj = Object.fromEntries(map.entries());
console.log(obj);
// { banana: 1, orange: 2, meat: 4 }

 - map.entries()는 맵의 [키, 값]을 요소로 가지는 이터러블을 반환합니다.

// .entries()를 생략해도 가능합니다!!
let obj2 = Object.fromEntries(map);
console.log(obj2);
// { banana: 1, orange: 2, meat: 4 }

 - Object.fromEntries는 인수로 이터러블 객체를 받기 때문에 짧게 줄인 코드도 이전 코드와 동일하게 동작합니다.


 

 

맵과 셋

 

ko.javascript.info