Melihat ini dan ini halaman MDN sepertinya satu-satunya perbedaan antara Maps dan WeakMaps adalah hilang "ukuran" properti untuk WeakMaps. Tapi apakah ini benar? Apa perbedaan diantara mereka?
key
tidak dapat dikumpulkan, karena dirujuk oleh Anda.
key
tidak dapat dikumpulkan, karena dirujuk oleh Anda.
Jawaban:
Dari halaman yang sama, bagian " Mengapa Peta Lemah ? " :
Pemrogram JavaScript yang berpengalaman akan melihat bahwa API ini dapat diimplementasikan dalam JavaScript dengan dua larik (satu untuk kunci, satu untuk nilai) yang digunakan bersama oleh 4 metode API. Implementasi seperti itu akan memiliki dua ketidaknyamanan utama. Yang pertama adalah pencarian O (n) (n adalah jumlah tombol di peta). Yang kedua adalah masalah kebocoran memori. Dengan peta yang ditulis secara manual, larik kunci akan menyimpan referensi ke objek utama, mencegahnya untuk dikumpulkan dari sampah. Dalam WeakMaps asli, referensi ke objek utama disimpan "dengan lemah" , yang berarti bahwa mereka tidak mencegah pengumpulan sampah jika tidak akan ada referensi lain ke objek tersebut.
Karena referensi lemah, kunci WeakMap tidak dapat dihitung (yaitu tidak ada metode yang memberi Anda daftar kunci). Jika ya, daftar tersebut akan bergantung pada status pengumpulan sampah, memperkenalkan non-determinisme.
[Dan itulah mengapa mereka juga tidak memiliki size
properti]
Jika Anda ingin memiliki daftar kunci, Anda harus menyimpannya sendiri. Ada juga proposal ECMAScript yang bertujuan untuk memperkenalkan set dan peta sederhana yang tidak akan menggunakan referensi yang lemah dan akan dapat dihitung.
- yang akan menjadi "normal" Map
s . Tidak disebutkan di MDN, tetapi dalam proposal harmoni , mereka juga memiliki items
, keys
dan values
metode generator dan mengimplementasikan Iterator
antarmuka .
new Map().get(x)
memiliki waktu pencarian yang hampir sama dengan membaca properti dari objek biasa?
WeakMap
masih memiliki larik (atau kumpulan entri lainnya), ini hanya memberi tahu pengumpul sampah bahwa itu adalah referensi yang lemah .
Keduanya berperilaku berbeda saat objek yang direferensikan oleh kunci / nilainya dihapus. Mari kita ambil contoh kode di bawah ini:
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);
})()
IIFE di atas dijalankan tidak ada cara kami dapat referensi {x: 12}
dan {y: 12}
lagi. Pengumpul sampah melanjutkan dan menghapus penunjuk b kunci dari "WeakMap" dan juga menghapus {y: 12}
dari memori. Tetapi dalam kasus "Peta", pengumpul sampah tidak menghapus penunjuk dari "Peta" dan juga tidak menghapus {x: 12}
dari memori.
Ringkasan: WeakMap memungkinkan pengumpul sampah melakukan tugasnya tetapi tidak dengan Map.
Referensi: http://qnimate.com/difference-between-map-and-weakmap-in-javascript/
map.entries().next().value // [{x:12}, 1]
WeakMap
hanya dapat memiliki kunci non-primitif (tidak ada string atau angka atau Symbol
s sebagai kunci, hanya array, objek, peta lain, dll.).
Map
tapi tidak diWeakMap
Mungkin penjelasan selanjutnya akan lebih jelas bagi seseorang.
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
Seperti yang Anda lihat, setelah menghapus k1
kunci dari memori kita masih bisa mengaksesnya di dalam peta. Pada saat yang sama menghapus k2
kunci WeakMap akan menghapusnya dariwm
referensi.
Itulah mengapa WeakMap tidak memiliki metode enumerable seperti forEach, karena tidak ada yang namanya daftar kunci WeakMap, mereka hanya referensi ke objek lain.
forEach
, (key, val)
seharusnya benar-benar(val, key)
Perbedaan lain (sumber: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap ):
Kunci dari WeakMaps adalah tipe Object saja. Tipe data primitif sebagai kunci tidak diperbolehkan (mis. Simbol tidak bisa menjadi kunci WeakMap).
String, angka, atau boolean juga tidak dapat digunakan sebagai WeakMap
kunci. A Map
dapat menggunakan nilai primitif untuk kunci.
w = new WeakMap;
w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key
m = new Map
m.set('a', 'b'); // Works
Dari Javascript.info
Peta - Jika kita menggunakan objek sebagai kunci dalam Peta biasa, maka saat Peta ada, objek itu juga ada. Ini menempati memori dan mungkin tidak dikumpulkan sampah.
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]
Mirip dengan itu, jika kita menggunakan objek sebagai kunci dalam Map biasa, maka selama Map ada, objek itu juga ada. Ini menempati memori dan mungkin tidak dikumpulkan sampah
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 - Sekarang, jika kita menggunakan objek sebagai kunci di dalamnya, dan tidak ada referensi lain ke objek itu - itu akan dihapus dari memori (dan dari peta) secara otomatis.
let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // overwrite the reference
// john is removed from memory!
WeapMap di javascript tidak menyimpan kunci atau nilai apa pun, hanya memanipulasi nilai kunci menggunakan id unik dan menentukan properti ke objek kunci.
karena ia mendefinisikan properti menjadi key object
menurut metode Object.definePropert()
, kunci tidak boleh berjenis primitif .
dan juga karena WeapMap sebenarnya tidak berisi pasangan nilai kunci, kita tidak bisa mendapatkan properti length dari weakmap.
dan juga nilai yang dimanipulasi diberikan kembali ke objek kunci, pengumpul sampah dengan mudah dapat mengumpulkan kunci jika tidak digunakan.
Kode contoh untuk implementasi.
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;
})();
referensi implementasi
id
, tetapi ini harus unik dengan menggunakan sesuatu Math.random dan Date.now (), dll. Dan dengan menambahkan id dinamis ini, poin pertama dapat diselesaikan. Bisakah Anda memberi saya solusi untuk dua poin terakhir.
WeakMap
kunci harus berupa objek, bukan nilai primitif.
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
Mengapa????
Mari kita lihat contoh di bawah ini.
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()
Jika kita menggunakan objek sebagai kunci reguler
Map
, maka sementaraMap
ada, objek itu juga ada. Ini menempati memori dan mungkin tidak dikumpulkan sampah.
WeakMap
berbeda secara fundamental dalam aspek ini. Itu tidak mencegah pengumpulan sampah objek utama.
let user = { name: "User" };
let weakMap = new WeakMap();
weakMap.set(user, "...");
user = null; // overwrite the reference
// 'user' is removed from memory!
jika kita menggunakan objek sebagai kunci di dalamnya, dan tidak ada referensi lain ke objek itu - itu akan dihapus dari memori (dan dari peta) secara otomatis.
WeakMap
tidak mendukung iterasi dan metode kunci () , nilai () , entri () , jadi tidak ada cara untuk mendapatkan semua kunci atau nilai darinya.
WeakMap hanya memiliki metode berikut:
Jelas seolah-olah sebuah objek telah kehilangan semua referensi lainnya (seperti 'pengguna' dalam kode di atas), maka objek tersebut akan dikumpulkan secara otomatis. Namun secara teknis itu tidak ditentukan secara pasti kapan pembersihan terjadi.
Mesin JavaScript memutuskan itu. Ini mungkin memilih untuk melakukan pembersihan memori segera atau menunggu dan melakukan pembersihan nanti ketika lebih banyak penghapusan terjadi. Jadi, secara teknis jumlah elemen saat ini dari a WeakMap
tidak diketahui. Mesin mungkin telah membersihkannya atau tidak atau melakukannya sebagian. Oleh karena itu, metode yang mengakses semua kunci / nilai tidak didukung.
Catatan: - Area utama aplikasi WeakMap adalah penyimpanan data tambahan. Seperti meng-cache sebuah objek hingga objek tersebut mengumpulkan sampah.