Looking bu ve bu onu Maps ve WeakMaps arasındaki tek fark gibi görünüyor MDN sayfaları WeakMaps için kayıp "boyutu" özelliktir. Ama bu doğru mu? Aralarındaki fark nedir?
key
sizin tarafınızdan referans verildiği için toplanamaz.
key
sizin tarafınızdan referans verildiği için toplanamaz.
Yanıtlar:
Gönderen çok aynı sayfada, bölüm " Neden Zayıf Harita? " :
Deneyimli JavaScript programcısı, bu API'nin JavaScript'te 4 API yöntemi tarafından paylaşılan iki diziyle (biri anahtarlar için, biri değerler için) uygulanabileceğini fark edecektir. Böyle bir uygulamanın iki ana sakıncası olacaktır. İlki bir O (n) aramasıdır (n, haritadaki tuşların sayısıdır). İkincisi, bellek sızıntısı sorunudur. Manuel olarak yazılan haritalarda, anahtar dizisi, anahtar nesnelere referansları saklar ve bunların gereksiz yere toplanmasını engeller. Yerel WeakMaps'te, anahtar nesnelere yapılan başvurular "zayıf" tutulur ; bu, nesneye başka bir başvuru olmaması durumunda çöp toplamayı engellemedikleri anlamına gelir.
Referansların zayıf olması nedeniyle, WeakMap anahtarları numaralandırılamaz (yani, size anahtarların bir listesini veren bir yöntem yoktur). Öyle olsalardı, liste çöp toplama durumuna bağlı olacak ve determinizm olmayacaktı.
[Ve bu yüzden size
mülkleri de yok ]
Bir anahtar listesine sahip olmak istiyorsanız, bunu kendiniz korumalısınız. Zayıf referanslar kullanmayan ve numaralandırılabilir basit setler ve haritalar sunmayı amaçlayan bir ECMAScript önerisi de vardır .
- "normal" Map
ler olurdu . MDN'yi de belirtildiği, ancak içinde değil uyum önerisi , o da var items
, keys
ve values
jeneratör yöntem ve uygulamak Iterator
arabirimi .
new Map().get(x)
, bir özelliği düz bir nesneden okumakla yaklaşık aynı arama süresine sahiptir?
WeakMap
hala bir dizi (veya başka bir dizi) girdiye sahiptir, sadece çöp toplayıcıya bunların zayıf referanslar olduğunu söyler .
Anahtarları / değerleri tarafından referans verilen bir nesne silindiğinde her ikisi de farklı davranır. Aşağıdaki örnek kodu alalım:
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);
})()
Yukarıdaki IIFE, referans verebilmemizin hiçbir yolu yoktur {x: 12}
ve {y: 12}
artık yürütülmektedir . Çöp toplayıcı devam eder ve anahtar b işaretçisini "WeakMap" den siler ve ayrıca {y: 12}
bellekten kaldırır . Ancak "Harita" durumunda, çöp toplayıcı "Harita" dan bir işaretçiyi kaldırmaz ve ayrıca {x: 12}
bellekten de kaldırmaz .
Özet: WeakMap çöp toplayıcının görevini yapmasına izin verir, ancak Harita yapmasına izin vermez.
Referanslar: http://qnimate.com/difference-between-map-and-weakmap-in-javascript/
map.entries().next().value // [{x:12}, 1]
WeakMap
sahip olabilir , ancak yalnızca ilkel olmayan anahtarlara sahip olabilir (anahtar olarak dizeler, sayılar veya s'ler Symbol
, yalnızca diziler, nesneler, diğer haritalar vb.).
Map
ama değilWeakMap
Belki bir sonraki açıklama birisi için daha net olacaktır.
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
Gördüğünüz gibi k1
, hafızadan anahtarı çıkardıktan sonra, ona haritanın içinden hala erişebiliyoruz. Aynı zamanda k2
WeakMap anahtarının kaldırılması onu wm
referans olarak da kaldırır .
Bu nedenle WeakMap, forEach gibi numaralandırılabilir yöntemlere sahip değildir, çünkü WeakMap anahtarlarının listesi diye bir şey yoktur, bunlar yalnızca başka nesnelere referanslardır.
forEach
, (key, val)
aslında olması gereken(val, key)
Başka bir fark (kaynak: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap ):
WeakMaps anahtarları yalnızca Object tipindedir. Anahtar olarak ilkel veri türlerine izin verilmez (örneğin, bir Sembol bir WeakMap anahtarı olamaz).
Bir dizge, sayı veya mantıksal WeakMap
anahtar olarak da kullanılamaz . A Map
, anahtarlar için ilkel değerler kullanabilir.
w = new WeakMap;
w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key
m = new Map
m.set('a', 'b'); // Works
Gönderen Javascript.info
Harita - Normal bir Haritada anahtar olarak bir nesne kullanırsak, Harita varken o nesne de var olur. Hafızayı kaplar ve çöp toplanmayabilir.
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]
Buna benzer şekilde, normal bir Harita'da anahtar olarak bir nesne kullanırsak, Harita varken o nesne de var olur. Hafızayı kaplar ve çöp toplanmayabilir
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 - Şimdi, anahtar olarak bir nesneyi kullanırsak ve bu nesneye başka referanslar yoksa - otomatik olarak bellekten (ve haritadan) kaldırılacaktır.
let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // overwrite the reference
// john is removed from memory!
Javascript'teki WeapMap herhangi bir anahtar veya değer içermez, sadece benzersiz bir kimlik kullanarak anahtar değerini işler ve anahtar nesneye bir özellik tanımlar.
özelliği key object
yönteme göre tanımladığından Object.definePropert()
, anahtar ilkel tür olmamalıdır .
ve ayrıca WeapMap aslında anahtar değer çiftleri içermediğinden, zayıf haritanın uzunluk özelliğini alamıyoruz.
ve ayrıca manipüle edilen değer anahtar nesneye geri atanır, çöp toplayıcı kullanılmadığı takdirde anahtarı kolayca toplayabilir.
Uygulama için örnek kod.
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;
})();
uygulama referansı
id
, ancak bu Math.random ve Date.now () vb. Kullanarak benzersiz olmalıdır. Ve bu dinamik kimliği ekleyerek ilk nokta çözülebilir. Lütfen son iki nokta için bana bir çözüm sunar mısınız?
WeakMap
anahtarlar, ilkel değerler değil, nesneler olmalıdır.
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
Neden????
Aşağıdaki örneğe bakalım.
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()
Normalde anahtar olarak bir nesneyi kullanırsak
Map
, o zamanMap
var olduğu sürece , o nesne de var olur. Hafızayı kaplar ve çöp toplanmayabilir.
WeakMap
bu açıdan temelde farklıdır. Anahtar nesnelerin çöp toplanmasını engellemez.
let user = { name: "User" };
let weakMap = new WeakMap();
weakMap.set(user, "...");
user = null; // overwrite the reference
// 'user' is removed from memory!
Anahtar olarak bir nesneyi kullanırsak ve bu nesneye başka referanslar yoksa, bellekten (ve haritadan) otomatik olarak kaldırılacaktır.
WeakMap
değil yineleme ve yöntemler desteklemek ) tuşları ( , değerleri () , girişler () , bu yüzden ondan tüm anahtarları veya değerleri almak için bir yolu yoktur.
WeakMap yalnızca aşağıdaki yöntemlere sahiptir:
Bu, bir nesne diğer tüm referansları kaybetmiş gibi açıktır (yukarıdaki koddaki 'kullanıcı' gibi), o zaman otomatik olarak çöp olarak toplanacaktır. Ancak teknik olarak temizleme işleminin ne zaman gerçekleştiği tam olarak belirtilmemiştir.
JavaScript motoru buna karar verir. Bellek temizlemeyi hemen gerçekleştirmeyi veya beklemeyi ve daha sonra daha fazla silme olduğunda temizlemeyi yapmayı seçebilir. Bu nedenle, teknik olarak a'nın mevcut eleman sayısı WeakMap
bilinmemektedir. Motor temizlemiş veya temizlememiş veya kısmen temizlemiş olabilir. Bu nedenle, tüm anahtarlara / değerlere erişen yöntemler desteklenmez.
Not: - WeakMap'in ana uygulama alanı ek bir veri depolamadır. Bir nesnenin çöp toplanana kadar önbelleğe alınması gibi.