[javascript] ES6 Map과 WeakMap의 차이점은 무엇입니까?

찾는 이지도와 WeakMaps 사이의 유일한 차이처럼 보인다 MDN 페이지 것은 WeakMaps에 대한 누락 “크기”속성입니다. 그러나 이것이 사실입니까? 그들 사이의 차이점은 무엇입니까?



답변

에서 매우 같은 페이지, 섹션 ” 약한 지도? :

숙련 된 JavaScript 프로그래머는이 API가 4 개의 API 메서드가 공유하는 두 개의 배열 (키용 하나, 값용 하나)을 사용하여 JavaScript에서 구현 될 수 있음을 알게 될 것입니다. 이러한 구현에는 두 가지 주요 불편 함이 있습니다. 첫 번째는 O (n) 검색입니다 (n은 맵의 키 수). 두 번째는 메모리 누수 문제입니다. 수동으로 작성된 맵을 사용하면 키 배열이 키 개체에 대한 참조를 유지하여 가비지 수집을 방지합니다. 네이티브 WeakMaps에서 키 객체에 대한 참조는 “약하게” 유지 됩니다. 즉, 객체에 대한 다른 참조가 없을 경우 가비지 수집을 방지하지 않습니다.

참조가 약하기 때문에 WeakMap 키는 열거 할 수 없습니다 (즉, 키 목록을 제공하는 메서드가 없습니다). 그럴 경우 목록은 가비지 수집 상태에 따라 달라지며 비결 정성을 도입합니다.

[그것도 size재산 이없는 이유입니다 ]

키 목록을 갖고 싶다면 직접 유지해야합니다.
약한 참조를 사용하지 않고 열거 할 수있는 간단한 집합과 맵을 도입하는 것을 목표로 하는 ECMAScript 제안 도 있습니다.

-이 될 것이다 “정상” Map . MDN에 언급,하지만하지 조화를 제안 , 그 또한 가지고 items, keysvalues생성 방법과 구현 Iterator인터페이스를 .


답변

키 / 값이 참조하는 객체가 삭제되면 둘 다 다르게 작동합니다. 아래 예제 코드를 살펴 보겠습니다.

var map = new Map();
var weakmap = new WeakMap();

(function(){
    var a = {x: 12};
    var b = {y: 12};

    map.set(a, 1);
    weakmap.set(b, 2);
})()

위의 인생은 우리가 참조 할 수있는 방법은 없습니다 실행 {x: 12}하고 {y: 12}더 이상은. 가비지 수집기는 계속해서 “WeakMap”에서 키 b 포인터를 삭제 {y: 12}하고 메모리 에서도 제거합니다 . 그러나“Map”의 경우 가비지 수집기는“Map”에서 포인터를 제거하지 않고 {x: 12}메모리 에서도 제거하지 않습니다 .

요약 : WeakMap을 사용하면 가비지 수집기가 작업을 수행 할 수 있지만 Map은 수행 할 수 없습니다.

참조 : http://qnimate.com/difference-between-map-and-weakmap-in-javascript/


답변

아마도 다음 설명은 누군가에게 더 분명 할 것입니다.

var k1 = {a: 1};
var k2 = {b: 2};

var map = new Map();
var wm = new WeakMap();

map.set(k1, 'k1');
wm.set(k2, 'k2');

k1 = null;
map.forEach(function (val, key) {
    console.log(key, val); // k1 {a: 1}
});

k2 = null;
wm.get(k2); // undefined

보시다시피 k1메모리에서 키를 제거한 후에도 지도 내에서 계속 액세스 할 수 있습니다. 동시에 k2WeakMap의 키를 제거하면 wm참조로도 제거됩니다 .

이것이 WeakMap이 forEach와 같은 열거 가능한 메서드가없는 이유입니다. WeakMap 키 목록과 같은 것이 없기 때문에 다른 개체에 대한 참조 일뿐입니다.


답변

또 다른 차이점 (출처 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap ) :

WeakMaps의 키는 Object 유형입니다. 키로서의 원시 데이터 유형은 허용되지 않습니다 (예 : Symbol은 WeakMap 키가 될 수 없음).

문자열, 숫자 또는 부울을 WeakMap키로 사용할 수도 없습니다 . A Map 키에 기본 값을 사용할 있습니다.

w = new WeakMap;
w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key

m = new Map
m.set('a', 'b'); // Works


답변

에서 Javascript.info

지도 -일반지도에서 객체를 키로 사용하면지도가 존재하는 동안 해당 객체도 존재합니다. 메모리를 차지하고 가비지 수집되지 않을 수 있습니다.

let john = { name: "John" };
let array = [ john ];
john = null; // overwrite the reference

// john is stored inside the array, so it won't be garbage-collected
// we can get it as array[0]

마찬가지로 일반지도에서 객체를 키로 사용하면지도가있는 동안 해당 객체도 존재합니다. 메모리를 차지하며 가비지 수집되지 않을 수 있습니다.

let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null; // overwrite the reference

// john is stored inside the map,
// we can get it by using map.keys()

WeakMap- 이제 객체를 키로 사용하고 해당 객체에 대한 다른 참조가 없으면 메모리 (및 맵)에서 자동으로 제거됩니다.

let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // overwrite the reference

// john is removed from memory!


답변

자바 스크립트의 WeapMap은 키 또는 값을 보유하지 않으며 고유 ID를 사용하여 키 값을 조작합니다. 하고 키 개체에 속성을 정의합니다.

이에 속성을 정의하기 때문에 key object방법으로 Object.definePropert(), 키 원시 형이 아니어야합니다 .

또한 WeapMap에는 실제로 키 값 쌍이 포함되어 있지 않기 때문에 weakmap의 길이 속성을 얻을 수 없습니다.

또한 조작 된 값은 키 객체에 다시 할당되며, 가비지 수집기는 사용하지 않는 경우 쉽게 키를 수집 할 수 있습니다.

구현을위한 샘플 코드.

if(typeof WeapMap != undefined){
return;
}
(function(){
   var WeapMap = function(){
      this.__id = '__weakmap__';
   }

   weakmap.set = function(key,value){
       var pVal = key[this.__id];
        if(pVal && pVal[0] == key){
           pVal[1]=value;
       }else{
          Object.defineProperty(key, this.__id, {value:[key,value]});
          return this;
        }
   }

window.WeakMap = WeakMap;
})();

구현 참조


답변

WeakMap 키는 원시 값이 아닌 객체 여야합니다.

let weakMap = new WeakMap();

let obj = {};

weakMap.set(obj, "ok"); // works fine (object key)

// can't use a string as the key
weakMap.set("test", "Not ok"); // Error, because "test" is not an object

왜????

아래 예를 보겠습니다.

let user = { name: "User" };

let map = new Map();
map.set(user, "...");

user = null; // overwrite the reference

// 'user' is stored inside the map,
// We can get it by using map.keys()

객체를 일반에서 키로 사용하면 존재 Map하는 동안
Map해당 객체도 존재합니다. 메모리를 차지하고 가비지 수집되지 않을 수 있습니다.

WeakMap이 측면에서 근본적으로 다릅니다. 키 개체의 가비지 수집을 방지하지 않습니다.

let user = { name: "User" };

let weakMap = new WeakMap();
weakMap.set(user, "...");

user = null; // overwrite the reference

// 'user' is removed from memory!

객체를 키로 사용하고 해당 객체에 대한 다른 참조가없는 경우 메모리 (및 맵)에서 자동으로 제거됩니다.

WeakMap 반복 및 메서드 키 () , 값 () , 항목 ()을 지원 하지 않습니다. 모든 키 또는 값을 가져올 방법이 없습니다.

WeakMap에는 다음 메서드 만 있습니다.

  • weakMap.get (키)
  • weakMap.set (키, 값)
  • weakMap.delete (키)
  • weakMap.has (키)

객체가 다른 모든 참조 (위 코드의 ‘user’와 같은)를 잃어버린 경우 자동으로 가비지 수집됩니다. 그러나 기술적으로는 정리가 발생하는시기가 정확히 지정되어 있지 않습니다.

JavaScript 엔진이이를 결정합니다. 메모리 정리를 즉시 수행하거나 더 많은 삭제가 발생할 때 기다렸다가 나중에 정리하도록 선택할 수 있습니다. 따라서 기술적으로 a의 현재 요소 개수 WeakMap는 알 수 없습니다. 엔진이 청소했거나 청소하지 않았거나 부분적으로 수행했을 수 있습니다. 따라서 모든 키 / 값에 액세스하는 메서드는 지원되지 않습니다.

참고 : -WeakMap의 주요 적용 영역은 추가 데이터 저장소입니다. 객체가 가비지 수집 될 때까지 객체를 캐싱하는 것과 같습니다.