Search
Duplicate

Map 오브젝트

1. Map오브젝트 형태, new Map()

Map 오브젝트

[Key / Value] pair collection
Map 오브젝트의 형태는 [key, value]형태로 대괄호 내에 key와 value를 작성합니다. 자바스크립트의 Map에서는 정말 다양형 타입을 key로 사용할 수 있는데 예제코드를 통해 알아봅니다.
cost obj = new Map([ ["key", "value"], [{book:200}, "오브젝트"], [100, "Number"], [Symbol(100), "symbol"] ]); for(let keyValue of obj){ console.log(keyValue); };
JavaScript
복사
[실행 결과]
["key", "value"] [{book:200}, "오브젝트"] [100, "Number"] [Symbol(100), "symbol"]
⇒ key의 타입으로 String, Object, Number, Symbol 이 사용됩니다 또한 Map의 key처리는 for-of문을 통해 작성한 순서대로 읽어서 처리할수도 있습니다.

new Map()

new 키워드를 사용해 Map의 인스턴스를 생성할 수 있습니다. 파라미터에는 이터러블 오브젝트를 작성할 수 있는데 만약 생성시점에서 파라미터를 다 가지고있는게 아니라면 인스턴스 생성후 추가해주는 방향으로 사용할 수도 있습니다.
const obj = new Map([ ["spring", "boot"], ["node", "js"] ]); console.log(obj); console.log(typeof obj);
JavaScript
복사
[실행 결과]
Map(2) {"spring" => "boot", "node" => "js"}
object
⇒ 초기값으로 이터러블 오브젝트를 작성해주며 대괄호 두개를 통해 2차원 배열로 작성해줬습니다.
Map 오브젝트는 Same-Value-Zero 비교 알고리즘을 따르기 때문에 key값을 비교하여 key 값이 같을경우 value가 대체됩니다. 여기서 key 값을 비교할때는 타입까지 비교하기 때문에 키 값이 100과 "100"이라면 다르다고 판단합니다.
const obj = new Map([ [100, "숫자 100"], ["100", "문자 100"], [100, "숫자 100 대체"], ]); for(let [key, value] of obj){ console.log(`${key} : ${value}`); };
JavaScript
복사
[실행 결과]
100 : 숫자 100 대체 100 : 문자 100
1.
["100", "문자 100"]
⇒ Map 내부에서 "100"이라는 key값을 찾지만 기존에 등록된 100은 타입이 다르기때문에 없는걸로 판단해서 다른 key값으로 등록됩니다.
2.
[100, "숫자 100 대체"]
⇒ Map 내부에서 100이라는 key값을 찾고 [100, "숫자 100"] 를 찾습니다. key의 값과 타입이 같기에 같은 key로 판단해 value를 대체합니다.
Same-Value-Zero비교 알고리즘

2. Map과 Object 비교

지금까지는 주로 Object를 이용해 key/value pair로 사용을 했습니다. 기존 Object를 사용해도 내부에 등록된 프로퍼티 이름으로 값을 꺼내 사용할 수 있는데 Map을 사용하려면 Map의 오브젝트 구조와 차이점을 알 필요가 있습니다.

Map 오브젝트 구조

1.
Map 오브젝트에는 get Symbol(Symbol.species)가 있습니다. 따라서, constructor를 오버라이드 할 수 있습니다.
2.
prototype을 펼치면 Symbol.iterator가 있습니다. 즉, 이터레이터 오브젝트를 반환받아 반복할수 있습니다.
그리고, Map은 배열과 구조가 유사한데 이 역시 Scope를 전개해서 알아봅시다.
const list = [1, 2]; const obj = new Map([ ["one", "첫 번째"], ["two", "두 번째"] ]); debugger
JavaScript
복사
Map 인스턴스인 obj를 전개하면 [[Entries]]가 있습니다. 대괄호 두 개는 엔진에서 설정하는것을 의미합니다. 이를 펼치면 0: {"key" ⇒ "value"} 형태로 나열되있는데 이는 배열구조와 유사합니다. Map또한 인덱스를 부여하여 저장하기에 배열처럼 이터레이션이 가능합니다. 배열과 맵 둘 다 요소 작성 순서대로 인덱스를 부여하여 해당 인덱스의 value로 입력값을 저장하는데 list는 value만 있는반면 map은 형태(key⇒value)로 저장된다는 점이 차이점입니다.

비교

1.
key
Map: 타입 제약 없음
Object: String, Symbol
2.
{key:value} 수
Map: size 프로퍼티로 구함.
Object: 전체를 읽어서 구해야 합니다.
3.
처리 시간: MDN
a.
key, value의 추가 삭제가 빈번할수록 Map이 더 뛰어난 성능을 보여줍니다.

3. 값 설정, 추출 메소드:set(), get(), has()

previous

Map 오브젝트에서 제공하는 set, get, has 메소드들은 MDN에도 이미 설명이 잘 나와있고 사용하는데 있어 어려운 함수가 아니기에 간단한 설명과 예제만 작성합니다.

set()

Map 인스턴스에 초기 생성자 파라미터로 이터러블 오브젝트를 작성할 수 있는데, 인스턴스 생성시점에서 파라미터가 아직 없다면 나중에라도 추가할 수 있어야하고 set()메소드를 통해 key/value를 넣어줄 수 있습니다. 그리고 동일하게 Same-Value-Zero 비교 알고리즘을 사용하기에 key값이 같으면 value가 대체됩니다.
let obj = new Map(); obj.set("one", 100); obj.set({}, "오브젝트"); obj.set(function(){}, "Function"); obj.set(new Number("100"), "인스턴스"); obj.set(NaN, "Not a Number"); for(let [key, value] of obj){ console.log(`${key}: ${value}`); };
JavaScript
복사
[실행 결과]
one: 100 [object Object]: 오브젝트 function(){}: Function 100: 인스턴스 NaN: Not a Number

get()

파라미터로 작성한 key 값이 map인스턴스 안에 있는지 검사후 있다면 해당 key의 pair인 value를 반환합니다. 만일 key 값이 같지 않거나 타입이 다를 경우 undefined를 반환합니다.
let obj = new Map([ ["one", 100], ["200", "String 타입"] ]); console.log(obj.get("one")); console.log(obj.get("two")); console.log(obj.get(200));
JavaScript
복사
[실행 결과]
100
undefined
undefined

has()

Map인스턴스에서 key의 존재 여부를 반환하는 메소드로 key가 있으면 true, 없으면 false반환
const obj = new Map([ ["one", 100] ]); console.log(obj.has("one")); console.log(obj.has("two"));
JavaScript
복사
[실행 결과]
true
false

4. Map과 이터레이터 오브젝트: entries(), keys(), values(), Symbol.iterator()

previous

Map 오브젝트에서 제공하는 set, get, has 메소드들은 MDN에도 이미 설명이 잘 나와있고 사용하는데 있어 어려운 함수가 아니기에 간단한 설명과 예제만 작성합니다.

entries()

Map 인스턴스로 이터레이터 오브젝트를 생성및 반환하는 메소드
Map인스턴스에 설정된 순서로 반환
next()로 [key, value] 반환
const obj = new Map([ ["one", 100], ["two", 200] ]); const iter = obj.entries(); console.log(iter.next()); console.log(iter.next()); console.log(iter.next());
JavaScript
복사
[실행 결과]
{value: [one, 100], done: false} {value: [two, 200], done: false} {value: undefined, done: true}

keys()

Map인스턴스의 key로 이터레이터 오브젝트를 생성, 반환
value는 포함하지않으며 Map인스턴스에 설정된 순서로 반환합니다.
next()로 key 반환
const obj = new Map([ ["one", 100], ["two", 200] ]); const iter = obj.keys(); console.log(iter.next()); console.log(iter.next()); console.log(iter.next());
JavaScript
복사
[실행 결과]
{value: "one", done: false} {value: "two", done: false} {value: undefined, done: true}

values()

Map인스턴스의 value로 이터레이터 오브젝트를 생성및 반환합니다.
key는 포함하지 않으며 Map인스턴스에 설정된 순서로 반환합니다.
next()로 value 반환
const obj = new Map([ ["one", 100], ["two", 200] ]); const iter = obj.values(); console.log(iter.next()); console.log(iter.next()); console.log(iter.next());
JavaScript
복사
[실행 결과]
{value: 100, done: false} {value: 200, done: false} {value: undefined, done: true}

Symbol.iterator()

Map인스턴스로 이터레이터 오브젝트를 생성, 반환
Map.prototype.entries()와 동일합니다.
next()로 [key, value] 반환
const obj = new Map([ ["one", 100], ["two", 200] ]); const iter = obj[Symbol.iterator](); console.log(iter.next()); console.log(iter.next()); console.log(iter.next());
JavaScript
복사
[실행 결과]
{value: [one, 100], done: false} {value: [two, 200], done: false} {value: undefined, done: true}

5. 콜백 함수, 삭제, 지우기: forEach(), delete, clear()

forEach()

Map 인스턴스를 반복하면서 callback 함수를 호출합니다.
map(), filter()등의 callback함수가 동반되는 메소드는 사용이 불가능합니다.
callback 함수에 넘겨주는 파라미터
value, key, Map 인스턴스 key, value순서가 아님
callback 함수에서 this사용
const obj = new Map([ ["one", 100], ["two", 200] ]); const callback = function(value, key, map){ console.log(`${key}, ${value}, ${this.check}`); }; obj.forEach(callback, {check: 50});
JavaScript
복사
[실행 결과]
one, 100, 50 two, 200, 50
1.
const callback = function(value, key, map){...}
⇒ 콜백함수를 일반 함수로 작성했는데 그 이유는 forEach()에서 두 번째 파라미터로 작성한 Object를 this로 바인딩시키기 위해서는 일반함수를 써야합니다. 만일 arrow function을 사용한다면 this는 window 오브젝트를 참조합니다.

delete()

Map 인스턴스에서 파라미터 값과 같은 entry 삭제
같은 key가 있으면 true반환하며 없으면 false를 반환
const obj = new Map([ ["one", 100], ["two", 200], [{}, "오브젝트"] ]); console.log(obj.delete("one")); console.log(obj.delete({})); console.log(obj.delete("three")); console.log(obj);
JavaScript
복사
[실행 결과]
true
false
false
Map(1) {"two" => 200}
1.
obj.delete("one")
⇒ obj 인스턴스 내부의 one 이라는 key를 찾아서 삭제한 뒤 true를 반환합니다.
2.
obj.delete({})
⇒ 얼핏 보면 둘 다 빈 오브젝트이니 가능할 것 같지만 두 오브젝트는 다른 메모리주소를 가지고 있기 때문에 다른 오브젝트이고 obj인스턴스내에서 key를 찾을 수 없기에 false입니다.
3.
obj.delete("three")
⇒ obj 인스턴스 내부의 three라는 key를 찾지만 찾을 수 없기에 false를 반환합니다.

clear()

Map인스턴스의 모든 entry를 지웁니다.
Map인스턴스 자체를 삭제하는것은 아니며 내부의 entry만 지웁니다.
따라서 [key, value]를 다시 추가할 수 있습니다.
내부 entry의 수를 알고싶다면 size 프로퍼티를 사용하면 됩니다.
length 프로퍼티와 다르게 size는 개발자가 수정할 수 없습니다.
const obj = new Map([ ["one", 100], ["two", 200] ]); console.log(obj.size); obj.clear(); console.log(obj.size, ",", obj); obj.set("add", "추가"); console.log(obj.size);
JavaScript
복사
[실행 결과]
2 0 "," Map(0) {} 1