Apa kegunaan sebenarnya dari WeakMap
struktur data yang diperkenalkan dalam ECMAScript 6?
Karena kunci dari peta yang lemah menciptakan referensi yang kuat untuk nilai yang sesuai, memastikan bahwa nilai yang telah dimasukkan ke dalam peta yang lemah tidak akan pernah hilang selama kuncinya masih hidup, itu tidak dapat digunakan untuk tabel memo, cache atau apa pun yang biasanya Anda gunakan menggunakan referensi lemah, peta dengan nilai lemah, dll.
Tampaknya bagi saya bahwa ini:
weakmap.set(key, value);
... hanyalah cara bundaran untuk mengatakan ini:
key.value = value;
Kasus penggunaan konkret apa yang saya lewatkan?
javascript
ecmascript-6
weakmap
Valderman
sumber
sumber
WeakMap
s dapat digunakan untuk mendeteksi kebocoran memori: stevehanov.ca/blog/?id=148Jawaban:
Secara fundamental
WeakMaps menyediakan cara untuk memperluas objek dari luar tanpa mengganggu pengumpulan sampah. Kapan pun Anda ingin memperluas objek tetapi tidak bisa karena disegel - atau dari sumber eksternal - WeakMap dapat diterapkan.
WeakMap adalah peta (kamus) tempat kunci lemah - yaitu, jika semua referensi ke kunci hilang dan tidak ada lagi referensi ke nilai - nilainya dapat berupa sampah yang dikumpulkan. Mari kita tunjukkan ini pertama melalui contoh, kemudian jelaskan sedikit dan akhirnya selesai dengan penggunaan nyata.
Katakanlah saya menggunakan API yang memberi saya objek tertentu:
Sekarang, saya punya metode yang menggunakan objek:
Saya ingin melacak berapa kali metode dipanggil dengan objek tertentu dan melaporkan jika itu terjadi lebih dari N kali. Secara naif orang akan berpikir untuk menggunakan Peta:
Ini berfungsi, tetapi memiliki kebocoran memori - kami sekarang melacak setiap objek perpustakaan yang diteruskan ke fungsi yang membuat objek perpustakaan tidak pernah menjadi sampah yang dikumpulkan. Sebaliknya - kita bisa menggunakan a
WeakMap
:Dan kebocoran memori hilang.
Gunakan kasing
Beberapa case yang dapat menyebabkan kebocoran memori dan diaktifkan oleh
WeakMap
s termasuk:Mari kita lihat penggunaan yang sebenarnya
Dapat digunakan untuk memperluas objek dari luar. Mari kita berikan contoh praktis (diadaptasi, semacam nyata - untuk menegaskan) dari dunia nyata Node.js.
Katakanlah Anda Node.js dan Anda memiliki
Promise
objek - sekarang Anda ingin melacak semua janji yang saat ini ditolak - namun, Anda tidak ingin mencegahnya dari sampah yang dikumpulkan seandainya tidak ada referensi.Sekarang, Anda tidak ingin menambahkan properti ke objek asli karena alasan yang jelas - jadi Anda terjebak. Jika Anda menyimpan referensi untuk janji-janji Anda menyebabkan kebocoran memori karena tidak ada pengumpulan sampah dapat terjadi. Jika Anda tidak menyimpan referensi maka Anda tidak dapat menyimpan informasi tambahan tentang janji individu. Skema apa pun yang melibatkan penyimpanan ID janji secara inheren berarti Anda memerlukan referensi untuk itu.
Masukkan WeakMaps
WeakMaps berarti bahwa kunci lemah. Tidak ada cara untuk menyebutkan peta yang lemah atau untuk mendapatkan semua nilainya. Di peta yang lemah, Anda bisa menyimpan data berdasarkan kunci dan ketika kunci mendapat sampah dikumpulkan begitu juga nilainya.
Ini berarti bahwa dengan janji Anda dapat menyimpan status tentangnya - dan objek itu masih dapat dikumpulkan sebagai sampah. Kemudian, jika Anda mendapatkan referensi ke suatu objek, Anda dapat memeriksa apakah Anda memiliki keadaan terkait dan melaporkannya.
Ini digunakan untuk menerapkan kait penolakan yang tidak ditangani oleh Petka Antonov karena ini :
Kami menyimpan informasi tentang janji di peta dan dapat mengetahui kapan janji yang ditolak ditangani.
sumber
useObj
contoh menggunakan aMap
dan bukan aWeakMap
kita menggunakan objek yang diteruskan sebagai kunci peta. Objek tidak pernah dihapus dari peta (karena kita tidak akan tahu kapan harus melakukannya) sehingga selalu ada referensi untuk itu dan itu tidak pernah bisa menjadi sampah yang dikumpulkan. Dalam contoh WeakMap segera setelah semua referensi lain ke objek hilang - objek dapat dihapus dariWeakMap
. Jika Anda masih tidak yakin dengan apa yang saya maksud, beri tahu sayacalled
Contoh Anda lebih baik ditulis menggunakan jsfiddle.net/f2efbm7z dan tidak menunjukkan penggunaan peta yang lemah. Bahkan, bisa ditulis lebih baik dalam total 6 cara, yang saya akan daftar di bawah ini.p[key_symbol] = data
. atau 2) penamaan unik;p.__key = data
. atau 3) ruang lingkup pribadi;(()=>{let data; p.Key = _=>data=_;})()
. atau 4) proksi dengan 1 atau 2 atau 3. atau 5) ganti / tambah kelas Janji dengan 1 atau 2 atau 3. atau 6) ganti / perpanjang kelas Janji dengan tupel anggota yang diperlukan. - Bagaimanapun, lemah peta tidak diperlukan kecuali Anda membutuhkan cache sensitif memori.Jawaban ini tampaknya bias dan tidak dapat digunakan dalam skenario dunia nyata. Harap baca apa adanya, dan jangan menganggapnya sebagai opsi aktual untuk hal lain selain eksperimen
Sebuah use case bisa digunakan sebagai kamus untuk pendengar, saya punya rekan kerja yang melakukan itu. Ini sangat membantu karena setiap pendengar secara langsung ditargetkan dengan cara melakukan sesuatu. Selamat tinggal
listener.on
.Tapi dari sudut pandang yang lebih abstrak,
WeakMap
sangat kuat untuk menurunkan material akses pada dasarnya apa pun, Anda tidak perlu ruang nama untuk mengisolasi anggotanya karena sudah tersirat oleh sifat struktur ini. Saya cukup yakin Anda bisa melakukan beberapa perbaikan memori besar dengan mengganti kunci objek yang canggung berlebihan (meskipun mendekonstruksi melakukan pekerjaan untuk Anda).Sebelum membaca apa selanjutnya
Saya sekarang menyadari bahwa penekanan saya bukanlah cara terbaik untuk mengatasi masalah dan seperti yang ditunjukkan Benjamin Gruenbaum (lihat jawabannya, jika belum di atas saya: p), masalah ini tidak dapat diselesaikan dengan cara biasa
Map
, karena itu akan bocor, jadi kekuatan utamaWeakMap
adalah bahwa itu tidak mengganggu pengumpulan sampah mengingat bahwa mereka tidak menyimpan referensi.Berikut adalah kode aktual rekan kerja saya (terima kasih kepada dia untuk berbagi)
Sumber lengkap di sini , ini tentang manajemen pendengar yang saya bicarakan di atas (Anda juga dapat melihat spesifikasi )
sumber
WeakMap
berfungsi dengan baik untuk enkapsulasi dan penyembunyian informasiWeakMap
hanya tersedia untuk ES6 ke atas. AWeakMap
adalah kumpulan pasangan kunci dan nilai di mana kunci harus menjadi objek. Dalam contoh berikut, kami membuat aWeakMap
dengan dua item:Kami menggunakan
set()
metode untuk mendefinisikan hubungan antara suatu objek dan item lain (string dalam kasus kami). Kami menggunakanget()
metode untuk mengambil item yang terkait dengan objek. Aspek yang menarik dariWeakMap
s adalah fakta bahwa ia memegang referensi yang lemah ke kunci di dalam peta. Referensi yang lemah berarti bahwa jika objek dihancurkan, pengumpul sampah akan menghapus seluruh entri dariWeakMap
, sehingga membebaskan memori.sumber
๐ ๐ฒ๐๐ฎ๐ฑ๐ฎ๐๐ฎ
Lemah Maps dapat digunakan untuk menyimpan metadata tentang elemen DOM tanpa mengganggu pengumpulan sampah atau membuat rekan kerja marah pada kode Anda. Misalnya, Anda bisa menggunakannya untuk mengindeks semua elemen dalam halaman web secara numerik.
๐ช๐ถ๐๐ต๐ผ๐๐ ๐ช๐ฒ๐ฎ๐ธ๐ ๐ฎ๐ฝ๐ ๐ผ๐ฟ ๐ช๐ฒ๐ฎ๐ธ๐ฆ๐ฒ๐๐:
๐จ๐๐ถ๐ป๐ด ๐ช๐ฒ๐ฎ๐ธ๐ ๐ฎ๐ฝ๐ ๐ฎ๐ป๐ฑ ๐ช๐ฒ๐ฎ๐ธ๐ฆ๐ฒ๐๐:
๐ง๐ต๐ฒ ๐๐ถ๐ณ๐ณ๐ฒ๐ฟ๐ฒ๐ป๐ฐ๐ฒ
Perbedaannya mungkin terlihat dapat diabaikan, selain dari fakta bahwa versi peta lemah lebih panjang, namun ada perbedaan besar antara dua bagian kode yang ditunjukkan di atas. Dalam cuplikan kode pertama, tanpa peta yang lemah, potongan kode menyimpan referensi di antara elemen DOM. Ini mencegah elemen DOM dari pengumpulan sampah.
(i * i) % len
mungkin tampak seperti bola aneh yang tidak akan digunakan siapa pun, tetapi pikirkan lagi: banyak kode produksi memiliki referensi DOM yang terpental di seluruh dokumen. Sekarang, untuk potongan kode kedua, karena semua referensi ke elemen lemah, ketika Anda menghapus node, browser dapat menentukan bahwa node tidak digunakan (tidak dapat dijangkau oleh kode Anda), dan dengan demikian hapus dari memori. Alasan mengapa Anda harus khawatir tentang penggunaan memori, dan jangkar memori (hal-hal seperti potongan kode pertama di mana elemen yang tidak digunakan disimpan dalam memori) adalah karena lebih banyak penggunaan memori berarti lebih banyak upaya browser GC (untuk mencoba membebaskan memori ke avert a browser crash) berarti pengalaman menjelajah lebih lambat dan terkadang browser mengalami crash.Adapun polyfill untuk ini, saya akan merekomendasikan perpustakaan saya sendiri ( ditemukan di sini @ github ). Ini adalah pustaka yang sangat ringan yang hanya akan mengisinya tanpa kerangka kerja yang terlalu rumit yang mungkin Anda temukan di polyfill lainnya.
~ Selamat coding!
sumber
elements
ke nol dan Anda selesai: Ini akan menjadi GCed. & Re " Referensi DOM yang terpental di seluruh dokumen ", tidak masalah sama sekali: Setelah tautan utamaelements
hilang, semua referensi bundar akan di-GCed. Jika elemen Anda menahan referensi ke elemen yang tidak diperlukan, maka perbaiki kode dan setel ref ke nol ketika Anda selesai menggunakannya. Itu akan GCed. Peta kelemahan tidak diperlukan .elements
ke null tidak akan mengizinkan browser untuk menambahkan elemen dalam situasi cuplikan pertama. Ini karena Anda menetapkan properti khusus pada elemen, dan kemudian elemen-elemen itu masih dapat diperoleh, dan properti kustom mereka masih dapat diakses, sehingga mencegah salah satu dari mereka dari menjadi GC'ed. Anggap saja seperti rantai cincin logam. Solongas Anda memiliki akses ke setidaknya satu tautan di rantai, Anda dapat memegang tautan itu di rantai, dan dengan demikian mencegah seluruh rantai barang agar tidak jatuh ke jurang.Saya menggunakan
WeakMap
untuk cache dari memoisasi bebas khawatir dari fungsi yang mengambil objek tidak berubah sebagai parameternya.Memoisasi adalah cara yang bagus untuk mengatakan "setelah Anda menghitung nilai, simpanlah sehingga Anda tidak perlu menghitungnya lagi".
Ini sebuah contoh:
Tampilkan cuplikan kode
Beberapa hal yang perlu diperhatikan:
sumber
Saya memiliki case use berdasarkan fitur sederhana ini / Contoh untuk WeakMaps.
MENGELOLA KOLEKSI PENGGUNA
Aku mulai dengan
User
Obyek yang sifat termasukfullname
,username
,age
,gender
dan metode yang disebutprint
yang mencetak ringkasan dibaca manusia dari sifat-sifat lainnya.Saya kemudian menambahkan Peta yang dipanggil
users
untuk menyimpan koleksi beberapa pengguna yang dikunci olehusername
.Penambahan Koleksi juga membutuhkan fungsi pembantu untuk menambah, mendapatkan, menghapus Pengguna dan bahkan fungsi untuk mencetak semua pengguna demi kelengkapan.
Dengan semua kode di atas berjalan, katakanlah NodeJS , hanya
users
Peta yang memiliki referensi ke Objek Pengguna dalam seluruh proses. Tidak ada referensi lain untuk masing-masing Objek Pengguna.Menjalankan kode ini sebagai shell NodeJS interaktif, seperti Contoh saya menambahkan empat pengguna dan mencetaknya:
TAMBAHKAN INFO LEBIH LANJUT UNTUK PENGGUNA TANPA MEMODIFIKASI KODE YANG ADA
Sekarang katakanlah fitur baru diperlukan di mana setiap pengguna tautan Platform Media Sosial (SMP) perlu dilacak bersama dengan Objek Pengguna.
Kuncinya di sini adalah juga bahwa fitur ini harus diimplementasikan dengan intervensi minimal terhadap kode yang ada.
Ini dimungkinkan dengan WeakMaps dengan cara berikut.
Saya menambahkan tiga WeakMaps terpisah untuk Twitter, Facebook, LinkedIn.
Fungsi pembantu,
getSMPWeakMap
ditambahkan hanya untuk mengembalikan WeakMap yang terkait dengan nama SMP yang diberikan.Fungsi untuk menambahkan tautan SMP pengguna ke SMP WeakMap yang diberikan.
Fungsi untuk mencetak hanya pengguna yang hadir di SMP yang diberikan.
Anda sekarang dapat menambahkan tautan SMP untuk para pengguna, juga dengan kemungkinan setiap pengguna memiliki tautan pada beberapa SMP.
... melanjutkan dengan Contoh sebelumnya, saya menambahkan tautan SMP ke pengguna, banyak tautan untuk pengguna, Bill dan Sarah, lalu mencetak tautan untuk setiap SMP secara terpisah:
Sekarang katakanlah seorang Pengguna dihapus dari
users
Peta dengan menelepondeleteUser
. Itu menghapus satu-satunya referensi ke Objek Pengguna. Ini pada gilirannya juga akan menghapus tautan SMP dari semua / semua SMP WeakMaps (oleh Garbage Collection) karena tanpa Objek Pengguna tidak ada cara untuk mengakses tautan SMP mana pun.... melanjutkan dengan Contoh, saya menghapus Bill pengguna dan kemudian mencetak tautan SMP yang dikaitkan dengannya:
Tidak ada persyaratan kode tambahan untuk menghapus tautan SMP secara terpisah dan kode yang ada sebelum fitur ini tidak dimodifikasi.
Jika ada cara lain untuk menambahkan fitur ini dengan / tanpa WeakMaps, jangan ragu untuk berkomentar.
sumber