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

참조 : 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));



답변

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

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

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

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

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


답변

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

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

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

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

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

의 단점은 Map무엇입니까?

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


답변

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

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

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


답변

과의 차이점 중 하나는 다음 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"}


답변

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

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

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 평가 개체


답변

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


답변