2013-07-09 16 views
9

ECMAScript 6 wprowadza słabe mapy, dostępne w pliku Node.JS v0.11.3 z flagą --harmony. Rozważ następujące.Opis słabych map

let weakMap = WeakMap(); 
let key = []; 
let rubbish = 'fish cans'; 

weakMap.set(key, rubbish); 
rubbish = 'empty bottle'; 

// Prints "fish cans" 
console.log(weakMap.get(key)); 

Byłem pod wrażeniem, że dla słabych map, odniesienie od klucza do wartości jest słaby, tak, że jeśli tylko odniesienie do wartości jest kluczem, następnie wartość może nie dłuższy być dostępnym.

Dlaczego więc wartość 'fish cans' jest nadal dostępna i czy nie są gromadzone śmieci? Zmienna rubbish nie odwołuje się już do niego, a odniesienie z key do 'fish cans' jest słabe, tj. Nieistniejące z punktu widzenia śmieciarza. czego mi brakuje?

+1

Zgaduję, że wartość * nadal * może być dostępna tylko dlatego, że śmieciarz nie przeszedł jeszcze przez ulicę. Innymi słowy, może gdybyś spróbował, że jakiś czas po tym nie zadziała? –

+0

Sposobem sprawdzenia, czy tak jest, byłoby uruchomienie sadystycznej pętli przydziałów, w których silnik byłby zmuszony do załadunku GC. Jeśli nadal tam jest, coś go trzyma. –

Odpowiedz

16

słaba część dotyczy kluczy, nie wartości. Z obecnym projekcie:

WeakMap mają na celu zapewnienie mechanizmu dynamicznego powiązania państwa z obiektu w taki sposób, aby nie „przeciekały” zasobów pamięci, jeśli w przypadku braku WeakMap, obiekt inaczej stało się niedostępne i podlega rekultywacji zasobów przez mechanizmy zbierania śmieci implementacji.

Say masz elementu DOM i chcesz skojarzyć niektóre dane z nim i używać WeakMap na to: weakMap.set(domElement, data);. Gdy element DOM zostanie usunięty, wówczas wpis na słabej mapie zostanie również usunięty.

Z drugiej strony nie chcemy, aby dane były usuwane tak długo, jak długo istnieje element DOM, tylko dlatego, że poza słabą mapą nie ma innych odniesień.

Poza tym 'fish cans' jest typem pierwotnym i jako taki nie podlega zbiorom śmieci.

11

Dlaczego zatem wartość 'fish cans' jest nadal dostępna, a nie zebrane? Zmienna śmieci już go nie odwołuje, a odniesienie z klucza do 'fish cans' jest słabe, tj. Nieistniejące z punktu widzenia śmieciarza. czego mi brakuje?

Zmienna rubbish nigdy nie była tą, która musiała się z nią odwoływać. Asocjacja (odwołanie) od klucza do wartości nadal istnieje, dopóki klucz nie zostanie zebrany. Słabym punktem odniesienia, którego GC nie widzi, jest ten z mapy do pary klucz/wartość (ten, który uczyniłby mapę przeliczalną). Twój key jeszcze nadal istnieje i można dostać każdą wartość, którą dla niego przechowywane w mapie:

var map = WeakMap(), 
    key = []; 

map.set(key, 'fish cans'); 
console.log(map.get(key)); // Prints "fish cans" 

aby wykazać słabość, trzeba by użyć następujących:

var map = WeakMap(), 
    key = []; 

map.set(key, 'fish cans'); 
// map.size == 1 
key = null; 
// map.size == 0 - the fish cans got garbage-collected together with the key 
map.get(???) // impossible now 
0

Próbuję to również zrozumieć. Myślę, że ustęp powiedział tak:

var key={a:1}; 
var wm=new WeakMap(); 


wm.set(key,"value"); 
wm.get(key); //you can get "value"; 

key=undefined; 
console.log(wm.get(key));//error.original key have no longer existed. so "value" is not longer existed as well. 

Ze względu na WeakMap nie ma sposobu, aby pobrać klucze, nie ma sposobu, aby ta „wartość” więcej.

jeśli użyjemy mapy(), ze względu na to, że mamy klawisze(), wpisy(), chociaż utracono wartość zmiennej kluczowej, "wartość" nadal może zostać odzyskana.

var key={a:1}; 
var m=new Map(); 


m.set(key,"value"); 
console.log(m.keys().next());; //you can get "value"; 

key=undefined; 
console.log(m.get(m.keys().next().value));//you can get "value"; 

Wniosek:

Jeśli kluczowym przedmiotem WeakMap straciły swój wniosek ten klucz i wartość będą zbierane śmieci, jak również (bo logicznie niedostępne). W ten sposób można zapobiec wyciekom pamięci.

Jeśli klucz obiektu z Mapa utracił swoje odniesienie, ten klucz i wartość będą nadal dostępne do momentu usunięcia lub wyczyszczenia. Więc trzeba mieć świadomość wyciek pamięci podczas rozwoju

Wystarczy znaleźć link o zrozumienie weakmap i jego przypadków użycia: http://ilikekillnerds.com/2015/02/what-are-weakmaps-in-es6/

0

Dodaję to odpowiedź na adres/wyjaśnić następujące punkt:

Początkowa wartość zmiennej "rubbish" nigdy nie została zmutowana; wszystko, co osiągnąłeś na rubbish = 'empty bottle';, to powiązanie z pseudonimurubbish z inną wartością. Stąd nawet po wykonaniu rubbish = 'empty bottle'; wpis weakMap z kluczem "" nadal ma przypisaną wartość, która odwołuje się do oryginalnej wartości rubbish.

Następnie, aby wartość straciła swój związek z kluczem, należy zmienić wartość wartości zmiennej kluczowej (jak już wspomniano w odpowiedzi @ Bergi).

Należy pamiętać, że key.push("whatever"); nie oznacza zmiany . Ponownie jednak powtórzone jest key = []; równie dobrze jak key = null;. Zasadniczo każda zmiana przypisania będzie wymagała zmiany.