Map

Map 객체는 키-값 쌍을 저장하며 각 쌍의 삽입 순서도 기억하는 콜렉션입니다. 아무 값(객체와 원시 값)이라도 키와 값으로 사용할 수 있습니다.

설명

Map 객체는 요소의 삽입 순서대로 원소를 순회합니다. for...of 반복문은 각 순회에서 [key, value]로 이루어진 배열을 반환합니다.

키 동일성

  • 키 동일성은 sameValueZero 알고리즘에 기반합니다.
  • NaN !== NaN이지만, 그럼에도 NaNNaN과 일치한다고 간주하며, 다른 모든 값은 === 연산자의 결과를 따릅니다.
  • 현 ECMAScript 명세는 -0+0을 같은 값으로 처리하지만 초기 명세에서는 그렇지 않았습니다. 브라우저 호환성의 "Key equality for -0 and 0"을 참고하세요.

ObjectMap 비교

Object는 값에 키를 할당할 수 있고, 그 키로 값을 얻을 수 있고, 키를 삭제할 수 있으며 어떤 키에 값이 존재하는지 확인할 수 있다는 점에서 Map과 유사합니다. 이런 이유에 더해, 이전에는 내장된 대체제가 없었기 때문에, ObjectMap 대신 사용하곤 했습니다.

그러나 어떤 상황에선, Map을 선호해야 할 몇 가지 중요한 차이점이 있습니다.

Map Object
의도치 않은 키 Map은 명시적으로 제공한 키 외에는 어떤 키도 가지지 않습니다.

Object는 프로토타입을 가지므로 기본 키가 존재할 수 있습니다. 주의하지 않으면 직접 제공한 키와 충돌할 수도 있습니다.

참고: ES5부터, 프로토타입으로 인한 키 충돌은 Object.create(null)로 해결할 수 있지만, 실제로 쓰이는 경우는 적습니다.

키 자료형 Map의 키는 함수, 객체 등을 포함한 모든 값이 가능합니다. Object의 키는 반드시 String 또는 Symbol이어야 합니다.
키 순서

Map의 키는 정렬됩니다. 따라서 Map의 순회는 삽입순으로 이뤄집니다.

Object의 키는 정렬되지 않습니다.

참고: ECMAScript 201 이후로, 객체도 문자열과 Symbol 키의 생성 순서를 유지합니다. ECMEScript 2015 명세를 준수하는 JavaScript 엔진에서 문자열 키만 가진 객체를 순회하면 삽입 순을 따라갑니다.

크기 Map의 항목 수는 size 속성을 통해 쉽게 알아낼 수 있습니다. Object의 항목 수는 직접 알아내야 합니다.
순회 Map순회 가능하므로, 바로 순회할 수 있습니다. Object를 순회하려면 먼저 모든 키를 알아낸 후, 그 키의 배열을 순회해야 합니다.
성능 잦은 키-값 쌍의 추가와 제거에서 더 좋은 성능을 보입니다. 잦은 키-값 쌍의 추가와 제거를 위한 최적화가 없습니다.

생성자

Map()
새로운 Map 객체를 생성합니다.

속성

Map.length
값이 0인 속성입니다.
요소의 수는 Map.prototype.size로 알아낼 수 있습니다.
get Map[@@species]
파생 객체를 생성하는데 사용하는 생성자 함수입니다.
Map.prototype
Map 생성자의 프로토타입을 나타냅니다. 모든 Map 인스턴스에 속성을 추가할 수 있습니다.

Map 인스턴스

모든 Map 인스턴스는 Map.prototype을 상속합니다.

속성

Map.prototype.constructor
인스턴스의 프로토타입을 만드는 함수를 반환한다. 이것 Map 함수의 기본 값이다.
Map.prototype.size
Map 객체에 들어있는 key/value pair의 수를 반환한다.

메서드

Map.prototype.clear()
Map 객체의 모든 key/value pair를 제거한다.
Map.prototype.delete(key)
주어진 키(Key)와 해당되는 값(Value)를 제거하고 제거하기 전에 Map.prototype.has(key)가 반환했던 값을 반환한다. 그 후의 Map.prototype.has(key)는 false를 반환한다.
Map.prototype.entries()
Map 객체 안의 모든 요소들을 [key, value] 형태의 array 로 집어넣은 순서대로 가지고 있는 Iterator 객체를 반환한다.
Map.prototype.forEach(callbackFn[, thisArg])
Map 객체 안에 존재하는 각각의 key/value pair에 집어넣은 순서대로 callbackFn을 부른다. 만약 thisArg 매개변수가 제공되면, 이것이 각 callback의 this 값으로 사용된다.
Map.prototype.get(key)
주어진 키(Key)에 해당되는 값(value)을 반환하고, 만약 없으면 undefined를 반환한다.
Map.prototype.has(key)
Map 객체 안에 주어진 key/value pair가 있는지 검사하고 Boolean 값을 반환한다.
Map.prototype.keys()
Map 객체 안의 모든 키(Key)들을 집어넣은 순서대로 가지고 있는 Iterator 객체를 반환한다.
Map.prototype.set(key, value)
Map 객체에 주어진 키(Key)에 값(Value)를 집어넣고, Map 객체를 반환한다.
Map.prototype.values()
Map 객체 안의 모든 (Value)들을 집어넣은 순서대로 가지고 있는 Iterator 객체를 반환한다.
Map.prototype[@@iterator]()
Map 객체 안의 모든 요소들을 [key, value] 형태의 array 로 집어넣은 순서대로 가지고 있는 Iterator 객체를 반환한다.

예제

Map 객체 사용하기

let myMap = new Map()

let keyString = '문자열'
let keyObj    = {}
let keyFunc   = function() {}

// 값 설정
myMap.set(keyString, "'문자열'과 관련된 값")
myMap.set(keyObj, 'keyObj와 관련된 값')
myMap.set(keyFunc, 'keyFunc와 관련된 값')

myMap.size              // 3

// getting the values
myMap.get(keyString)    // "'문자열'과 관련된 값"
myMap.get(keyObj)       // "keyObj와 관련된 값"
myMap.get(keyFunc)      // "keyFunc와 관련된 값"

myMap.get('문자열')    // "'문자열'과 관련된 값"
                         // keyString === '문자열'이기 때문
myMap.get({})            // undefined, keyObj !== {}
myMap.get(function() {}) // undefined, keyFunc !== function () {}

Map의 키로 NaN 사용하기

NaN도 키로서 사용할 수 있습니다. 모든 NaN은 자기 자신과 동일하지 않지만(NaN !== NaN), NaN을 서로 구분할 수도 없기 때문에 아래 예제도 잘 동작합니다.

let myMap = new Map()
myMap.set(NaN, 'not a number')

myMap.get(NaN)
// "not a number"

let otherNaN = Number('foo')
myMap.get(otherNaN)
// "not a number"

for..ofMap 순회하기

Mapfor..of 반복문을 사용해 순회할 수 있습니다.

let myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')

for (let [key, value] of myMap) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

for (let key of myMap.keys()) {
  console.log(key)
}
// 0
// 1

for (let value of myMap.values()) {
  console.log(value)
}
// zero
// one

for (let [key, value] of myMap.entries()) {
  console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one

forEach()Map 순회하기

MapforEach() 메서드로 순회할 수 있습니다.

myMap.forEach(function(value, key) {
  console.log(key + ' = ' + value)
})
// 0 = zero
// 1 = one

Array 객체와의 관계

let kvArray = [['key1', 'value1'], ['key2', 'value2']]

// Use the regular Map constructor to transform a 2D key-value Array into a map
let myMap = new Map(kvArray)

myMap.get('key1') // returns "value1"

// Use Array.from() to transform a map into a 2D key-value Array
console.log(Array.from(myMap)) // Will show you exactly the same Array as kvArray

// A succinct way to do the same, using the spread syntax
console.log([...myMap])

// Or use the keys() or values() iterators, and convert them to an array
console.log(Array.from(myMap.keys())) // ["key1", "key2"]

명세

브라우저 호환성

BCD tables only load in the browser

같이 보기