ES6의지도 대 객체, 언제 사용합니까?


83

참조 : MDN 맵

런타임까지 키를 알 수없고 모든 키가 동일한 유형이고 모든 값이 동일한 유형 인 경우 객체에 대한 맵을 사용합니다.

개별 요소에서 작동하는 논리가있는 경우 개체를 사용합니다.

질문:

객체 위에지도를 사용하는 적용 가능한 예는 무엇입니까? 특히, "언제 런타임까지 키를 알 수 없습니까?"

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));

네, 알아 챘어요. 함수를 값으로 설정합니다. @JonathanLonowski 당신은 내가 상점이 :(이 쓰임새의 힘든 사고 있다고해야 할 때 생각할 수 있습니다.
매튜 우드에게

7
Object를 사용하여 일부 데이터를 연관시키려는 DOM 요소를 말할 때 사용할 수 있습니다. 요소의 ID를 객체의 키로 사용하는 대신 요소 자체를 맵의 키로 사용할 수 있으므로 요소에 ID (또는 객체 참조 이외의 다른 고유 식별자)가 있는지 여부는 신경 쓰지 않습니다. ) 또는 아닙니다.
RobG 2015 년

1
@RobG 약간의 추가 :이 경우 WeakMap도움이 될 수도 있습니다.
zerkms

1
나는 이것이 다른 모든 종류의 매핑에 대해 레코드 및 맵으로 객체를 사용하는 것을 제안한다고 생각합니다. I 레코드는 필드를 가진 사용자 객체와 필드의 고정 세트를 갖는 데이터 구조체 의미 name하고 id, 예를 들어.
Felix Kling

1
MDN 페이지를 읽었을 때 글 머리 기호 목록의 사용 사례가 인용 한 단락보다 훨씬 더 유용했습니다. 귀하의 제목에 제기 된 질문과 관련이 있습니다.
CodingIntrigue 2015 년

답변:


51

객체 위에지도를 사용하는 적용 가능한 예는 무엇입니까?

이미 좋은 예가 하나 있다고 생각합니다. Map객체 (Function 객체 포함)를 키로 사용할 때는 최소한 s 를 사용해야 합니다.

특히 "언제 키를 런타임까지 알 수 없습니까?"

컴파일 타임에 알려지지 않은 경우. 간단히 말해 키-값 컬렉션Map 이 필요할 때 항상를 사용해야합니다 . 컬렉션이 필요하다는 좋은 지표는 컬렉션에서 동적으로 값을 추가 및 제거 할 때, 특히 해당 값을 미리 알지 못하는 경우 (예 : 데이터베이스에서 읽음, 사용자 입력 등)입니다.

반대로 코드를 작성하는 동안 개체의 속성이 얼마나 많은지 알 때 (그 모양이 정적 인 경우) 개체를 사용해야합니다. @Felix가 말했듯이 기록 이 필요할 때 . 필요에 대한 좋은 지표는 필드에 다른 유형이 있고 대괄호 표기법을 사용할 필요가 없을 때 (또는 제한된 속성 이름 집합을 예상 할 때)입니다.


1
또는 다른 관점에서 : 당신은 데이터 수준 (예에서 개체의 속성을 반복 할 때마다 for..of대신 프로그램 레벨 (예 :의) for..in)을을 사용 Map. 이 응답 에서이 용어 대한 추가 정보 .

또한 키의 유형을 모르고 문자열을 키 데이터 유형으로 기대하지 않을 때마다 map stackoverflow.com/questions/32600157/…
Carmine Tambascia

26

ES2015에서 Map일반 객체를 사용하는 이유는 두 가지 뿐이라고 생각 합니다.

  • 객체 유형의 속성을 전혀 반복하고 싶지 않습니다.
  • 또는 그렇게하지만 속성 순서는 중요하지 않으며 반복 할 때 프로그램을 데이터 수준과 구별 할 수 있습니다.

부동산 주문은 언제 중요하지 않습니까?

  • 단일 값과 명시 적으로 연관되어야하는 일부 기능 만있는 경우 (예 : Promise-미래 값에 대한 프록시-및 then/ catch)
  • "컴파일 타임"에 알려진 정적 속성 집합이있는 구조체 / 레코드와 유사한 데이터 구조가있는 경우 (일반적으로 구조체 / 레코드는 반복 할 수 없음)

다른 모든 경우에는 Map속성 순서를 유지하고 프로그램 ( Map객체에 할당 된 모든 속성 )을 데이터 수준 ( Map자체의 모든 항목)에서 분리하기 때문에 사용을 고려할 수 있습니다 .

의 단점은 Map무엇입니까?

  • 간결한 개체 리터럴 구문이 손실됩니다.
  • JSON.stringyfy에 대한 사용자 지정 대체자가 필요합니다.
  • 어쨌든 정적 데이터 구조에서 더 유용합니다.

이 줄은 저에게 매우 중요합니다. "순수한 해시 맵과 같은 객체보다 느릴 것입니다."성능 향상으로 인해 모든 객체를 맵으로 대체 할 생각이었습니다. 그러나 당신은 느린 ... 말할
mesqueeb

1
네가 옳아. Map순전히 해시를 기반으로하기 때문에 아마도 더 빠르지 만 Object조금 더 복잡합니다. 감사!

11

런타임까지 키를 알 수없고 모든 키가 동일한 유형이고 모든 값이 동일한 유형 인 경우 객체에 대한 맵을 사용합니다.

나는 누군가가 왜 그렇게 명백하게 잘못된 것을 쓰는지 전혀 모른다. 요즘 사람들은 MDN에서 점점 더 잘못되거나 의심스러운 콘텐츠를 찾고 있습니다.

그 문장의 어떤 것도 정확하지 않습니다. 맵을 사용하는 주된 이유는 객체 값 키를 원할 때입니다. 값이 같은 유형이어야한다는 생각은 당연히 그럴 수도 있지만 말도 안됩니다. 런타임까지 키를 알 수 없을 때 객체를 사용해서는 안된다는 생각은 똑같이 터무니 없습니다.


1
나는 그 아이디어에 대해 무엇이 그렇게 터무니 없는지 보지 못합니까? 컬렉션이 필요한 경우 일반적으로 엄격하게 형식이 지정됩니다 (물론 예외가있을 수 있음). 또한 컬렉션을 위해 더 이상 객체를 사용하지 않는 Map것이 좋은 조언 이라고 생각합니다 .
Bergi

컬렉션은 일반적으로 엄격하게 형식화된다는 것은 엄격하게 형식화 된 것이 컬렉션이어야한다고 말하는 것과 논리적으로 구별됩니다.

1
네, 조금 이상하다고 생각하지만 아이디어는 괜찮습니다. "런타임 전까지는 키를 알 수 없다"고 이미 컬렉션을 만들고 있다고 생각한 것 같습니다. 더 나은 표현에 대한 아이디어가 있습니까?
Bergi

1
동의합니다. MDN은 매우 좋은 문서를 가지고 있지만 API 문서 문서화에 충실해야하며 프로그래밍 조언을 제공하지 않아야합니다.
AlexG

5

과의 차이점 중 하나는 다음 MapObject같습니다.

Map복잡한 데이터 유형을 키로 사용할 수 있습니다. 이렇게 :

const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'

주의 : 복잡한 데이터 유형의 경우 값을 얻으려면 키와 동일한 참조를 전달해야합니다.

Object, 간단한 데이터 유형 ( number, string) 만 키로 허용합니다.

const a = {};
a[document.body] = 'stackoverflow';

console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}

2

이 질문은 그러나 그것이 닫힐 때까지 거기에서 내 대답이 있습니다 .

다른 답변 외에도지도가 개체보다 조작하기가 더 다루기 어렵고 장황하다는 것을 발견했습니다.

obj[key] += x
// vs.
map.set(map.get(key) + x)

이것은 코드가 짧을수록 더 빨리 읽고, 더 직접적으로 표현하고, 프로그래머의 머리 속에 더 잘 보관 되기 때문에 중요 합니다.

또 다른 측면 : set ()은 값이 아닌 맵을 반환하기 때문에 할당을 연결하는 것이 불가능합니다.

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map

지도 디버깅도 더 고통 스럽습니다. 아래에서는지도에 어떤 키가 있는지 실제로 볼 수 없습니다. 그렇게하려면 코드를 작성해야합니다.

Map Iterator를 평가 해보세요.

모든 IDE에서 개체를 평가할 수 있습니다.

WebStorm 평가 개체


6
이것은 " 물체 위에지도를 사용하는 적용 가능한 예는 무엇입니까? " 라는 질문에 전혀 대답하지 않습니다.
Bergi

6
답변을 교차 게시하지 마십시오. 그리고 아니요, 질문은 중복이 아닙니다.
Bergi

1

Objects는 Map키를 값으로 설정하고, 해당 값을 검색하고, 키를 삭제하고, 키에 무언가가 저장되어 있는지 감지 할 수 있다는 점 에서 s 와 유사합니다 . 이 때문에 (그리고 내장 된 대안이 없었기 때문에) Objects는 Map역사적 으로 s 로 사용되었습니다 . 그러나 Map특정 경우에 선호 하는 것을 사용하는 중요한 차이점이 있습니다.

  • 의 키 ObjectStrings 및 Symbols이지만 Map함수, 객체 및 모든 기본 요소를 포함하여 a의 모든 값이 될 수 있습니다 .
  • 의 키 Map는 정렬되지만 객체에 추가 된 키는 정렬되지 않습니다. 따라서 반복 할 때 Map객체는 삽입 순서대로 키를 반환합니다.
  • Mapsize속성 수는 Object수동으로 결정해야하는 반면 속성 으로 쉽게 크기를 얻을 수 있습니다 .
  • A Map는 반복 가능하므로 직접 반복 할 수있는 반면, 반복 Object하려면 어떤 방식으로 키를 가져 와서 반복해야합니다.
  • An Object에는 프로토 타입이 있으므로주의하지 않으면 키와 충돌 할 수있는 기본 키가 맵에 있습니다. ES5에서는를 사용하여 무시할 수 map = Object.create(null)있지만 거의 수행되지 않습니다.
  • A Map는 키 쌍을 자주 추가 및 제거하는 시나리오에서 더 잘 수행 될 수 있습니다.

MDN

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.