Front-End/JavaScript

[JavaScript] Map Object (맵)

Voyage_dev 2022. 4. 3. 11:11

자바스크립트에서 map은 두 가지이다

 1. Array.prototype.map() : 특정 배열 내 모든 요소에 대해 각각 함수를 적용하고, 새로운 배열로 만들어서 반환한다. 이때 원본 배열에는 영향을 주지 않는다

 2. Map : Java의 HashMap와 같은 key:value로 이루어진 자료구조

자바스크립트를 공부하다가 Map이 Java와는 다른 걸 느꼈다. Java에서 Map 객체는 키-값을 쌍으로 저장하며 각 쌍의 삽입 순서도 기억하는 콜렉션이다. 아무 값이라도 키와 값으로 사용할 수 있다. 즉, key:value 형식으로 저장되며, key 값을 사용하여 해당 key에 맞는 value값을 가져올 수 있다

let max = new Map();

// set으로 맵 객체에 삽입
max.set("id", 0);
max.set("이름", "마이클");
max.set("전공", "영문학");
max.set("나이", 25);

// 이차원 배열로 넘겨주는 것도 가능합니다
let michael = new Map([
    ["id", 0],
    ["이름", "마이클"],
    ["전공", "영문학"],
    ["나이", 29]
])

// get으로 맵 객체 조회
max.get("이름"); // "마이클"

// delete로 삭제
max.delete("나이"); // 삭제가 성공하면 true를 반환

// clear로 맵 안의 프로퍼티 전부삭제
max.clear();
  • 맴 객체는 기존 객체와는 다르게 메소드만을 이용해 값을 넣고 뺀다
  • 기본적으로 삽입, 조회, 삭제를 할 수 있다

Array.map()

이러한 map 메서드는 배열을 반복해주는데, callback 함수에서 reutnr한 값으로 (each) 요소를 수정해 준다. map 메서드의 리턴값은 수정된 값으로 생성된 배열이다

const numbers = [1, 2, 3, 4, 5]; 
const result = numbers.map(number => number * number); 

console.log(numbers); // [1, 2, 3, 4, 5]; 
console.log(result); // [1, 4, 9, 16, 25]

  • 주어진 array의 값들을 map으로 제곱을 해서 다시 result안에 배열을 만들어준다
  • 여기서 numbers라는 배열에는 아무런 영향이 없는 걸 볼 수 있다

위에 예시를 for문으로 돌린다면

const numbers = [1, 2, 3, 4, 5]; 
const result = []; for (i = 0; i < numbers.length; i++) { 
	result.push(numbers[i] * numbers[i]); 
} 

console.log(result); // [1, 4, 9, 16, 25]
  • 보이다시피 map메서드는 간결하지만 for문을 사용하면 순환이라는 부분까지 직접 처리해야 하기 때문에 좀 더 길고 간결하지가 않다

장점

문자열 아닌 값도 키로 사용 가능하다

객체에서는 문자열 (string) 혹은 심볼 (symbol)만 프로퍼티의 키로 사용할 수 있었지만 맵 객체에서는 함수나 객체를 포함해서 모든 자료형이 키로 쓰일 수 있다

  • 문자열이 아닌 숫자일 때 보기 더 편한 경우도 있다

메서드 사용의 명확성

객체처럼 . 이나 []로 접근하지 않고 메소드만으로 객체의 프로퍼티들을 수정하거나 조회할 수 있으므로 객체보다 동작과 의도를 더 정확하게 보여준다

let maxInfoObj = {
    name:"voyage",
    age:29,
    major:"경영정보",
}

const maxInfoMap = new Map([
    ["name", "voyage"],
    ["age", 29],
    ["major", "경영정보"],
])

// 객체 : let으로 선언해 빈 객체 할당해서 빈 객체로 초기화
maxInfoObj = {} 

// 맵 객체 : clear 메소드 사용해 빈 맵 객체로 초기화
maxInfoMap.clear()

깔끔한 순회

맴 객체의 가장 장점이라고 생각되는 부분이다. 맴 객체는 그 자체로 for..of문을 통해 순회가 가능하다. 맵 이터레이터의 형태로 이루어지는데 키-값을 쌍으로 묶은 배열이다. entries 메소드로 확인할 수 있다

const maxInfoMap = new Map([
    ["name", "voyage"],
    ["age", 29],
    ["major", "경영정보"],
])

maxInfoMap.entries();
// MapIterator { ["name", "voyage"],["age", 29],["major", "경영정보"]}

for (const [key, value] of maxInfoMap) {
    console.log(key, value);
}

// 결과
// "name" "voyage"
// "age" 29
// "major" "경영정보"

주의사항

  • map 함수는 객체를 직접 사용하거나 변경시키지는 않지만 callback 함수를 통해 수정할 수 있으며 이는 문제를 발생시키는 원인이 된다
  • callback 함수가 호출되는 범위는 콜백함수가 처음 호출되기 이전이며, map이 순회하는 도중에 추가된 요소는 접근하지 않는다. 반대로 순회하는 도중 수정이 일어나면 변경된 값이 콜백함수에 전달되고 삭제된 요소는 접근하지 않는다
// array 요소가 추가되는 경우 
const numbers = [1, 2, 3, 4, 5]; 
const result = numbers.map(number => { 
	numbers.push(number); 
return number * number; 
}); 

console.log(result); // [1, 4, 9, 16, 25]; 

// array 요소가 수정되는 경우 
const numbers = [1, 2, 3, 4, 5]; 
const result = numbers.map(number => { 
	numbers.pop(); return number * number; 
}); 

console.log(result); // [1, 4, 9, empty × 2];

결론

맵 객체는 객체의 프로퍼티를 자주 변경해야할 때 빛을 발한다. 메서드 이름들이 예측 가능하여 동작이 명확하고, 기존 객체와 달리 순회도 쉽게 이러우져 데이터를 조작하기 적합하다

출처 : 아래의 사이트들을 보면서 큰 공부 하였습니다

https://maxkim-j.github.io/posts/js-map

https://erim1005.tistory.com/entry/Javascript-에서-Object를-해시맵처럼-사용하지-마세요

https://dev-note-97.tistory.com/276

https://7942yongdae.tistory.com/48

https://www.robinwieruch.de/javascript-map-array/