찾는 이 와 이 이지도와 WeakMaps 사이의 유일한 차이처럼 보인다 MDN 페이지 것은 WeakMaps에 대한 누락 "크기"속성입니다. 그러나 이것이 사실입니까? 그들 사이의 차이점은 무엇입니까?
key
귀하가 참조하기 때문에 수집 할 수 없습니다.
key
귀하가 참조하기 때문에 수집 할 수 없습니다.
답변:
에서 매우 같은 페이지, 섹션 " 왜 약한 지도? " :
숙련 된 JavaScript 프로그래머는이 API가 4 개의 API 메서드가 공유하는 두 개의 배열 (키용 하나, 값용 하나)을 사용하여 JavaScript에서 구현 될 수 있음을 알게 될 것입니다. 이러한 구현에는 두 가지 주요 불편 함이 있습니다. 첫 번째는 O (n) 검색입니다 (n은 맵의 키 수). 두 번째는 메모리 누수 문제입니다. 수동으로 작성된 맵을 사용하면 키 배열이 키 개체에 대한 참조를 유지하여 가비지 수집을 방지합니다. 네이티브 WeakMaps에서 키 객체에 대한 참조는 "약하게" 유지 됩니다. 즉, 객체에 대한 다른 참조가 없을 경우 가비지 수집을 방지하지 않습니다.
참조가 약하기 때문에 WeakMap 키는 열거 할 수 없습니다 (즉, 키 목록을 제공하는 메서드가 없습니다). 그럴 경우 목록은 가비지 수집 상태에 따라 달라지며 비결 정성을 도입합니다.
[그것도 size
재산 이없는 이유입니다 ]
키 목록을 갖고 싶다면 직접 유지해야합니다. 약한 참조를 사용하지 않고 열거 할 수있는 간단한 집합과 맵을 도입하는 것을 목표로 하는 ECMAScript 제안 도 있습니다.
-이 될 것이다 "정상" Map
의 . MDN에 언급,하지만하지 조화를 제안 , 그 또한 가지고 items
, keys
및 values
생성 방법과 구현 Iterator
인터페이스를 .
new Map().get(x)
일반 객체에서 속성을 읽기와 같은 룩업 시간에 대해이있다?
키 / 값이 참조하는 객체가 삭제되면 둘 다 다르게 작동합니다. 아래 예제 코드를 살펴 보겠습니다.
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/
map.entries().next().value // [{x:12}, 1]
WeakMap
만 가질 수 있지만 기본이 아닌 키만 가질 수 있습니다 (문자열 또는 숫자 또는 Symbol
키로서의 s, 배열, 객체, 기타 맵 등).
Map
에 있지만WeakMap
아마도 다음 설명은 누군가에게 더 분명 할 것입니다.
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
메모리에서 키를 제거한 후에도 지도 내에서 계속 액세스 할 수 있습니다. 동시에 k2
WeakMap의 키를 제거하면 wm
참조로도 제거됩니다 .
이것이 WeakMap이 forEach와 같은 열거 가능한 메서드가없는 이유입니다. WeakMap 키 목록과 같은 것이 없기 때문에 다른 개체에 대한 참조 일뿐입니다.
forEach
, (key, val)
실제로 일해야한다(val, key)
또 다른 차이점 (출처 : 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;
})();
구현 참조
id
했지만 Math.random 및 Date.now () 등을 사용하여 고유해야합니다. 그리고이 동적 ID를 추가하면 첫 번째 요점이 해결 될 수 있습니다. 마지막 두 가지 요점에 대한 해결책을 알려주시겠습니까?
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에는 다음 메서드 만 있습니다.
객체가 다른 모든 참조 (위 코드의 'user'와 같은)를 잃어버린 경우 자동으로 가비지 수집됩니다. 그러나 기술적으로는 정리가 발생하는시기가 정확히 지정되어 있지 않습니다.
JavaScript 엔진이이를 결정합니다. 메모리 정리를 즉시 수행하거나 더 많은 삭제가 발생할 때 기다렸다가 나중에 정리하도록 선택할 수 있습니다. 따라서 기술적으로 a의 현재 요소 개수 WeakMap
는 알 수 없습니다. 엔진이 청소했거나 청소하지 않았거나 부분적으로 수행했을 수 있습니다. 따라서 모든 키 / 값에 액세스하는 메서드는 지원되지 않습니다.
참고 : -WeakMap의 주요 적용 영역은 추가 데이터 저장소입니다. 객체가 가비지 수집 될 때까지 객체를 캐싱하는 것과 같습니다.