JavaScript'te "zayıf bir referans" oluşturmak mümkün müdür?


98

Javascript'te başka bir nesneye "zayıf referans" oluşturmanın bir yolu var mı? İşte zayıf bir referansın ne olduğunu açıklayan wiki sayfası. İşte onları Java'da anlatan başka bir makale. Bu davranışı javascript'te uygulamanın bir yolunu düşünen var mı?


4
ES6 için zayıf referanslar tartışılıyor. Gözünü dört aç.
Ryan Smith

2
* Wiki.ecmascript.org/doku.php?id=strawman:weak_refs adresindeki resmi özellik wiki / tartışma , şu anda "Son değiştirilme tarihi: 2013/02/02 22:25" * esdiscuss.org/topic/what adresinde başka bir özellik tartışması -is-zayıf-referansların-durumu , şu anda son gönderi "Paz 3 Mar 11:56:05 PST 2013"
Destiny Architect

Çoğu durumda WR'ler, şu adreste tartışılan , Geçmiş Dinleyici Sorununu çözme girişimidir : [ stackoverflow.com/questions/43758217/… . Bu sorunun iyi bir cevabı olsaydı, WR'lere fazla ihtiyaç olacağını düşünmüyorum.
James

@supercat Geçmiş dinleyici sorusuna bir yanıt gönderdim .
James

Yanıtlar:


39

JavaScript'te zayıf referanslar için dil desteği yoktur. Manuel referans saymayı kullanarak kendiniz yuvarlayabilirsiniz, ancak özellikle düzgün bir şekilde değil. Bir proxy sarmalayıcı nesnesi oluşturamazsınız, çünkü JavaScript'te nesneler ne zaman çöp olarak toplanacaklarını asla bilemezler.

Böylece, 'zayıf referansınız', basit bir aramada, referans ekle ve referans kaldır yöntemiyle bir anahtar (örneğin, tam sayı) haline gelir ve artık manuel olarak izlenen referanslar olmadığında, giriş silinebilir ve gelecekteki aramalar açık bırakılabilir. null döndürmek için bu anahtar.

Bu gerçekten zayıf bir referans değildir, ancak aynı problemlerin bazılarını çözebilir. Bir DOM Düğümü veya olay işleyicisi ile bununla ilişkilendirilmiş bir nesne arasında bir referans döngüsü olduğunda tarayıcılardan (tipik olarak IE, özellikle eski sürümler) bellek sızıntısını önlemek için genellikle karmaşık web uygulamalarında yapılır. Bu durumlarda tam bir referans sayma şeması gerekli olmayabilir.


2
Kodu dikkatlice incelemedim (veya kullanmadım), ancak es- lab'da temel WeakMap öykünmesi sağlayan bir komut dosyası var . Aurora 6 (Mozilla), standart olmayan bir WeakMap uygulamasına sahiptir .
theazureshadow

2
ES6 ile bu cevap artık doğru değil. Aşağıdaki
cevabıma

9
Hala doğru, çünkü ES6 WeakMap'ler gerçek anlamda zayıf referanslar değil. WeakMap'ler nesneleri yalnızca anahtar olarak kabul eder ve bu nesnelere yapılan referanslar zayıf bir şekilde tutulur. Stackoverflow.com/questions/32397729/… sayfasına
CodeManX

Zayıf bir haritayı taklit etmek için bir sınıf yazdım ve buraya gönderdim: stackoverflow.com/a/47017206/491553
Ryan Shillington


12

Güncelleme: Eylül 2019

Henüz zayıf referanslar kullanmak mümkün değil, ancak JavaScript'teki WeakRefs Work In Progress (Devam Ediyor) olduğundan büyük olasılıkla yakında mümkün olacak . Detaylar aşağıda.

Teklif

Şu anda Aşama 3'te olan teklif , tam bir spesifikasyona sahip olduğu ve daha fazla iyileştirmenin uygulamalardan ve kullanıcılardan geri bildirim gerektireceği anlamına gelir .

WeakRef önerisi işlevselliği iki büyük yeni parçalarını kapsar:

  • WeakRef sınıfıyla nesnelere zayıf referanslar oluşturma
  • FinalizationGroup sınıfıyla nesneler çöpte toplandıktan sonra kullanıcı tanımlı sonlandırıcıları çalıştırma

Kullanım durumları

Bir birincil kullanımı zayıf referanslar için bunun bir önbellek veya haritalama görünür, çünkü büyük bir nesne yalnızca yaşatılmaktadır olmadığını arzu nereye, büyük nesneleri tutan önbelleklerini ya eşleştirmeleri uygulamaktır.

Sonlandırma , program yürütme için erişilemez hale gelen bir nesneden sonra temizlenecek kodun yürütülmesidir. Kullanıcı tanımlı sonlandırıcılar, birkaç yeni kullanım durumunu etkinleştirir ve çöp toplayıcının bilmediği kaynakları yönetirken bellek sızıntılarının önlenmesine yardımcı olabilir.

Kaynak ve daha fazla okuma

https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references


1
Firefox Nightly, WeakRef için deneysel destek ekledi. WeakSet'in yinelenebilir bir sürümünü oluşturmak için onu kullanan bir örnek uygulama: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
seanlinsley

3

Gerçekten zayıf referanslar, hayır, henüz değil (ancak tarayıcı üreticileri konuya bakıyor). Ama burada zayıf referansların nasıl simüle edileceğine dair bir fikir var.

Nesnelerinizi içinden geçirdiğiniz bir önbellek oluşturabilirsiniz. Bir nesne depolandığında, önbellek, nesnenin ne kadar bellek kullanacağına dair bir tahmin tutar. Görüntüleri saklama gibi bazı öğeler için bu, çalışmak için basittir. Diğerleri için bu daha zor olacaktır.

Bir nesneye ihtiyacınız olduğunda, önbellekten onu istersiniz. Önbellekte nesne varsa, döndürülür. Orada yoksa, öğe oluşturulur, depolanır ve ardından iade edilir.

Zayıf referanslar, tahmin edilen toplam bellek miktarı belirli bir seviyeye ulaştığında, önbellek kaldırma öğeleri tarafından simüle edilir. Hangi öğelerin en az kullanıldığını, ne sıklıkta alındıklarına ve ne kadar zaman önce çıkarıldıklarına göre ağırlıklandırılarak tahmin edecektir. Öğeyi oluşturan kod önbelleğe kapanış olarak aktarılırsa bir 'hesaplama' maliyeti de eklenebilir. Bu, önbelleğin oluşturulması veya üretilmesi çok pahalı olan öğeleri tutmasına izin verir.

Silme algoritması anahtardır, çünkü bunu yanlış yaparsanız, o zaman en popüler öğeleri kaldırabilirsiniz. Bu korkunç performansa neden olur.

Önbellek, depolanan nesnelere kalıcı referansları olan tek nesne olduğu sürece , yukarıdaki sistem gerçek zayıf referanslara bir alternatif olarak oldukça iyi çalışmalıdır.


25
Zayıf referanslar için söylediklerinizin çoğu alakasız değil mi?
Erik Kaplun

22
@ JL235 - zayıf referanslar için önemli kullanım önbellekler için değil olay işleyiciler içindir. Var olduğu halde başka bir olayı gözlemlemesi gereken bir nesnem var - ancak bunun bir bildirim listesinde yer almasının GC amaçları için bir referans teşkil etmesini istemiyorum.
Malvolio

7
Zayıf referansların önbelleğe alma ile hiçbir ilgisi yoktur. Zayıf bir referans, bir şeyi takip etmek istediğiniz anlamına gelir, ancak izlenmekte olan nesneye ilişkin kalan referanslar yoksa, silinmesine izin verirsiniz.
fabspro

8
Otomatik süre sonu için zayıf referanslar kullanarak bir önbellek oluşturmanın açıkça bir kullanım durumu vardır.
Phil Freeman 08

5
Önbelleğe alma, geleneksel olarak zayıf referansların en önemli nedenidir. Olay işleyici DOM olayı sadece bazı IE kaşifleri hatalı bir şeydir.
axkibe


2

Yukarıda JL235'in önerdiği gibi , zayıf bir referansı taklit etmek için bir önbelleğe alma mekanizması kullanmak mantıklıdır. Zayıf referanslar yerel olarak mevcut olsaydı, aşağıdaki gibi bir davranış gözlemlersiniz:

this.val = {};
this.ref = new WeakReference(this.val);
...
this.ref.get(); // always returns val
...
this.val = null; // no more references
...
this.ref.get(); // may still return val, depending on already gc'd or not

Oysa bir önbellekle şunları gözlemlersiniz:

this.val = {};
this.key = cache.put(this.val);
...
cache.get(this.key); // returns val, until evicted by other cache puts
...
this.val = null; // no more references
...
cache.get(this.key); // returns val, until evicted by other cache puts

Bir referansın sahibi olarak, bir değere ne zaman atıfta bulunduğuna dair herhangi bir varsayımda bulunmamalısınız, bu, bir önbellek kullanmaktan farklı değildir.



-4

EcmaScript 6 (ES Harmony) bir WeakMap nesnesine sahiptir. Modern tarayıcılar arasında tarayıcı desteği oldukça iyidir (Firefox'un son 3 sürümü, Chrome ve hatta yaklaşan bir IE sürümü bile desteklemektedir).


29
Bu tam olarak aynı değil. A WeakMap, nesnelere zayıf referanslar vermez - WeakMap'teki zayıf referanslar değerler değil, anahtarlardır . Haritada zayıf referansların bulunması yalnızca bir bellek sızıntısı önleme mekanizmasıdır ve başka türlü kullanıcı tarafından gözlemlenemez.
EyasSH

1
Zayıf olanın değerler değil anahtarlar olduğu konusunda haklısınız. Ancak zayıf referansları kullanmanın tüm amacı, referans verilen nesnenin çöp toplamasına izin vermektir. OP, ikincisi genişletemeyeceğiniz bir nesneye bir kimlik eklemekle ilgili iki bağlantı yayınladı ve aslında JavaScript'in WeakMap'in Java eşdeğeri olan WeakHashMap'i kullanmanızı önerir.
thelastshadow

12
çünkü zayıf bir başvuru uygulamak için WeakMap kullanarak iyi şanslar weakmap.get(new String('any possible key that has ever existed or ever will exist'))olacak hep olacak undefined. Yararlı değil . Aşağı oylama!
user3338098

-5

http://www.jibbering.com/faq/faq_notes/closures.html

ECMAScript otomatik çöp toplamayı kullanır. Spesifikasyon ayrıntıları tanımlamaz, bunu uygulayıcılara ayırması için bırakır ve bazı uygulamaların çöp toplama işlemlerine çok düşük bir öncelik verdiği bilinmektedir. Ancak genel fikir şudur: eğer bir nesneye atıfta bulunulamaz hale gelirse (kodun çalıştırılması için erişilebilir bırakılmaması durumunda) çöp toplama için kullanılabilir hale gelir ve gelecekte bir noktada yok edilir ve tükettiği tüm kaynaklar serbest bırakılır ve geri döndürülür. yeniden kullanım için sisteme.

Bu normalde bir yürütme bağlamından çıkıldığında meydana gelir. Kapsam zinciri yapısı, Aktivasyon / Değişken nesnesi ve işlev nesneleri dahil olmak üzere yürütme bağlamında oluşturulan nesneler artık erişilebilir olmayacak ve bu nedenle çöp toplama için kullanılabilir hale gelecektir.

Yani, zayıf olanlar yok, sadece artık mevcut olmayanlar.


10
Zayıf referanslar kullanmanın tek nedeni referans döngülerinden kaçınmak değildir. Nesne örneği havuzlama / önbelleğe alma vb. İçin çok kullanışlıdırlar.
kabarık

WeakReference'ın tanımı sorun değil. Ayrıca yukarıdaki yoruma katıldığı gibi.
Yuri Yaryshev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.