เป็นไปได้ไหมที่จะสร้าง "การอ้างอิงที่ไม่เหมาะสม" ในจาวาสคริปต์


98

มีวิธีใดบ้างในจาวาสคริปต์ในการสร้าง "การอ้างอิงที่อ่อนแอ" ไปยังวัตถุอื่น นี่คือหน้าวิกิที่อธิบายว่าการอ้างอิงที่ไม่เหมาะสมคืออะไร นี่คือบทความอื่นที่อธิบายถึงสิ่งเหล่านี้ใน Java ใครสามารถคิดวิธีการนำพฤติกรรมนี้ไปใช้ในจาวาสคริปต์ได้หรือไม่?


4
มีการกล่าวถึงการอ้างอิงที่อ่อนแอสำหรับ ES6 กลอกตา.
Ryan Smith

2
* วิกิ / การอภิปรายข้อมูลจำเพาะอย่างเป็นทางการที่wiki.ecmascript.org/doku.php?id=strawman:weak_refsปัจจุบัน“ แก้ไขล่าสุด: 2013/02/02 22:25” * การอภิปรายเกี่ยวกับข้อมูลจำเพาะอื่น ๆ ที่esdiscuss.org/topic/what - เป็นสถานะของการอ้างอิงที่อ่อนแอปัจจุบันโพสต์ล่าสุด“ อา 3 มี.ค. 11:56:05 PST 2013”
Destiny Architect

ในกรณีส่วนใหญ่ WRs เป็นความพยายามในการแก้ปัญหาตัวฟังที่หมดอายุซึ่งจะกล่าวถึงที่นี่: [ stackoverflow.com/questions/43758217/… . หากคำถามนั้นมีคำตอบที่ดีฉันไม่คิดว่าจะต้องมี WRs มากนัก
James

@supercat ผมได้โพสต์คำตอบของคำถามที่ห่างหายไปฟัง
James

คำตอบ:


39

ไม่มีการรองรับภาษาสำหรับจุดอ่อนใน JavaScript คุณสามารถหมุนของคุณเองโดยใช้การนับอ้างอิงด้วยตนเอง แต่ไม่ราบรื่นเป็นพิเศษ คุณไม่สามารถสร้างวัตถุห่อหุ้มพร็อกซีได้เนื่องจากในวัตถุ JavaScript ไม่มีทางรู้ว่าเมื่อใดที่พวกเขากำลังจะถูกรวบรวมขยะ

ดังนั้น 'การอ้างอิงที่ไม่เหมาะสม' ของคุณจึงกลายเป็นกุญแจสำคัญ (เช่นจำนวนเต็ม) ในการค้นหาอย่างง่ายโดยใช้วิธีการอ้างอิงเพิ่มเติมและการลบการอ้างอิงและเมื่อไม่มีการอ้างอิงที่ติดตามด้วยตนเองอีกต่อไปรายการจะถูกลบทิ้งโดยปล่อยให้มีการค้นหาในอนาคต คีย์นั้นเพื่อคืนค่าว่าง

นี่ไม่ใช่จุดอ่อน แต่สามารถแก้ปัญหาเดียวกันได้ โดยทั่วไปจะทำในเว็บแอปพลิเคชันที่ซับซ้อนเพื่อป้องกันการรั่วไหลของหน่วยความจำจากเบราว์เซอร์ (โดยทั่วไปคือ IE โดยเฉพาะรุ่นเก่ากว่า) เมื่อมีการวนรอบอ้างอิงระหว่างโหนด DOM หรือตัวจัดการเหตุการณ์และวัตถุที่เกี่ยวข้องเช่นการปิด ในกรณีเหล่านี้อาจไม่จำเป็นต้องใช้รูปแบบการนับอ้างอิงแบบเต็ม


2
ฉันยังไม่ได้ตรวจสอบอย่างรอบคอบ (หรือใช้) รหัส แต่ ES-Lab มีสคริปต์ให้พื้นฐานการจำลอง WeakMap ออโรร่า 6 (Mozilla) มีที่ไม่ได้มาตรฐานการดำเนินงาน WeakMap
theazureshadow

2
ด้วย ES6 คำตอบนี้ไม่ถูกต้องอีกต่อไป ดูคำตอบของฉันด้านล่างstackoverflow.com/a/28567560/745190
thelastshadow

9
ยังคงถูกต้องเนื่องจาก ES6 WeakMaps ไม่ใช่การอ้างอิงที่อ่อนแอจริง WeakMaps ยอมรับออบเจ็กต์เป็นคีย์เท่านั้นและการอ้างอิงถึงอ็อบเจ็กต์เหล่านี้จะถูกยึดไว้อย่างอ่อน ดูstackoverflow.com/questions/32397729/…
CodeManX

ฉันเขียนคลาสเพื่อเลียนแบบแผนที่ที่อ่อนแอและโพสต์ไว้ที่นี่: stackoverflow.com/a/47017206/491553
Ryan Shillington


12

อัปเดต: กันยายน 2019

ยังไม่สามารถใช้การอ้างอิงที่อ่อนแอได้ แต่ส่วนใหญ่แล้วจะเป็นไปได้ในไม่ช้าเนื่องจากWeakRefsใน JavaScript กำลังดำเนินการอยู่ รายละเอียดด้านล่าง.

ข้อเสนอ

ข้อเสนออยู่ในขั้นตอนที่ 3ซึ่งหมายความว่ามีคุณสมบัติครบถ้วนและการปรับแต่งเพิ่มเติมจะต้องได้รับการตอบรับจากการใช้งานและผู้ใช้

WeakRefข้อเสนอครอบคลุมสองชิ้นใหม่ที่สำคัญของการทำงาน:

  • การสร้างการอ้างอิงที่อ่อนแอไปยังอ็อบเจ็กต์ด้วยคลาส WeakRef
  • การรันโปรแกรมสุดท้ายที่ผู้ใช้กำหนดเองหลังจากอ็อบเจ็กต์ถูกรวบรวมโดยใช้คลาส FinalizationGroup

ใช้กรณี

การใช้งานหลักสำหรับการอ้างอิงที่อ่อนแอคือการใช้แคชหรือการแมปที่ถือวัตถุขนาดใหญ่ซึ่งต้องการให้วัตถุขนาดใหญ่ไม่คงอยู่เพียงเพราะมันปรากฏในแคชหรือการแมป

Finalizationคือการเรียกใช้โค้ดเพื่อล้างข้อมูลหลังจากอ็อบเจ็กต์ที่ไม่สามารถเข้าถึงได้เพื่อเรียกใช้งานโปรแกรม โปรแกรมปิดท้ายที่ผู้ใช้กำหนดจะเปิดใช้งานกรณีการใช้งานใหม่ ๆ และสามารถช่วยป้องกันการรั่วไหลของหน่วยความจำเมื่อจัดการทรัพยากรที่ตัวรวบรวมขยะไม่ทราบ

ที่มาและอ่านเพิ่มเติม

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


1
Firefox Nightly ได้เพิ่มการสนับสนุนทดลองสำหรับ WeakRef นี่คือตัวอย่างการนำไปใช้เพื่อสร้าง WeakSet เวอร์ชันที่ทำซ้ำได้: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
seanlinsley

3

การอ้างอิงที่อ่อนแออย่างแท้จริงยังไม่มี (แต่ผู้ผลิตเบราว์เซอร์กำลังดูเรื่องนี้) แต่นี่คือแนวคิดเกี่ยวกับวิธีจำลองการอ้างอิงที่อ่อนแอ

คุณสามารถสร้างแคชที่คุณขับเคลื่อนวัตถุของคุณผ่าน เมื่อวัตถุถูกเก็บไว้แคชจะคอยคาดเดาว่าวัตถุจะใช้หน่วยความจำเท่าใด สำหรับบางรายการเช่นการจัดเก็บภาพการดำเนินการนี้ตรงไปตรงมา สำหรับคนอื่นสิ่งนี้จะยากกว่า

เมื่อคุณต้องการวัตถุคุณก็ขอให้แคชมัน หากแคชมีอ็อบเจ็กต์จะถูกส่งคืน หากไม่มีรายการนั้นจะถูกสร้างขึ้นจัดเก็บแล้วส่งคืน

การอ้างอิงที่อ่อนแอถูกจำลองโดยรายการลบแคชเมื่อจำนวนหน่วยความจำที่คาดการณ์ไว้ทั้งหมดถึงระดับหนึ่ง จะทำนายว่ารายการใดถูกใช้น้อยที่สุดโดยพิจารณาจากความถี่ในการดึงข้อมูลโดยให้น้ำหนักตามระยะเวลาที่นำออกไป นอกจากนี้ยังสามารถเพิ่มต้นทุน 'การคำนวณ' ได้หากรหัสที่สร้างรายการถูกส่งไปยังแคชเป็นการปิด สิ่งนี้จะช่วยให้แคชสามารถเก็บรายการที่มีราคาแพงมากในการสร้างหรือสร้าง

อัลกอริทึมการลบเป็นกุญแจสำคัญเพราะถ้าคุณทำผิดคุณอาจต้องลบรายการยอดนิยมออกไป ซึ่งจะทำให้ประสิทธิภาพแย่มาก

ตราบใดที่แคชเป็นวัตถุเดียวที่มีการอ้างอิงถาวรไปยังอ็อบเจ็กต์ที่จัดเก็บดังนั้นระบบข้างต้นควรทำงานได้ดีเป็นทางเลือกสำหรับการอ้างอิงที่อ่อนแอจริง


25
สิ่งที่คุณพูดส่วนใหญ่ไม่เกี่ยวข้องกับจุดอ่อนใช่หรือไม่?
Erik Kaplun

22
@ JL235 - การใช้งานที่สำคัญสำหรับการอ้างอิงที่อ่อนแอไม่ใช่สำหรับแคช แต่สำหรับตัวจัดการเหตุการณ์ ฉันมีวัตถุบางอย่างที่ในขณะที่มีอยู่ควรสังเกตเหตุการณ์อื่น - แต่ฉันไม่ต้องการให้ข้อเท็จจริงที่ว่ามันอยู่ในรายการการแจ้งเตือนถือเป็นการอ้างอิงสำหรับวัตถุประสงค์ของ GC
Malvolio

7
การอ้างอิงที่อ่อนแอไม่เกี่ยวข้องกับการแคช การอ้างอิงที่ไม่ชัดเจนหมายความว่าคุณต้องการติดตามบางสิ่งบางอย่าง แต่หากไม่มีการอ้างอิงที่เหลือไปยังวัตถุที่กำลังติดตามอยู่คุณจะอนุญาตให้ลบได้
fabspro

8
มีกรณีการใช้งานอย่างชัดเจนสำหรับการสร้างแคชโดยใช้การอ้างอิงที่อ่อนแอสำหรับการหมดอายุโดยอัตโนมัติ
Phil Freeman

5
การแคชเป็นเหตุผลหลักสำหรับการอ้างอิงที่อ่อนแอ ตัวจัดการเหตุการณ์ DOM เป็นเพียงบางสิ่งที่มีข้อบกพร่องของ IE explorer เท่านั้น
axkibe


2

การใช้กลไกการแคชเพื่อเลียนแบบการอ้างอิงที่อ่อนแอตามที่JL235แนะนำไว้ข้างต้นนั้นสมเหตุสมผล หากมีการอ้างอิงที่อ่อนแอโดยกำเนิดคุณจะสังเกตเห็นพฤติกรรมเช่นนี้:

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

ในขณะที่คุณจะสังเกตเห็นแคช:

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

ในฐานะผู้ถือข้อมูลอ้างอิงคุณไม่ควรตั้งสมมติฐานใด ๆ เกี่ยวกับเวลาที่อ้างอิงถึงค่าซึ่งไม่ต่างจากการใช้แคช



-4

EcmaScript 6 (ES Harmony) มีวัตถุWeakMap การรองรับเบราว์เซอร์ในเบราว์เซอร์สมัยใหม่นั้นค่อนข้างดี (Firefox, chrome และเวอร์ชัน IE ที่กำลังจะมาถึง 3 เวอร์ชันล่าสุดก็รองรับ)


29
นี่ไม่เหมือนกันแน่ ๆ WeakMapไม่ให้อ้างอิงอ่อนแอ objects-- มันไม่ได้เป็นค่าที่มีการอ้างอิงที่อ่อนแอใน WeakMap แต่กุญแจ ความจริงที่ว่าการอ้างอิงที่อ่อนแอมีอยู่ในแผนที่เป็นเพียงกลไกการป้องกันการรั่วไหลของหน่วยความจำและผู้ใช้ไม่สามารถสังเกตเห็นได้
EyasSH

1
คุณถูกต้องที่เป็นกุญแจที่อ่อนแอไม่ใช่ค่านิยม แต่จุดประสงค์ทั้งหมดของการใช้การอ้างอิงที่อ่อนแอคือเพื่อให้สามารถรวบรวมขยะของวัตถุที่อ้างอิงได้ OP โพสต์ลิงก์สองลิงก์โดยที่สองเกี่ยวกับการเพิ่ม id ให้กับอ็อบเจ็กต์ที่คุณไม่สามารถขยายได้และในความเป็นจริงแนะนำให้ใช้ WeakHashMap ซึ่งเป็น Java ที่เทียบเท่ากับ WeakMap ของ JavaScript
thelastshadow

12
ขอให้โชคดีในการใช้ WeakMap เพื่อใช้การอ้างอิงที่อ่อนแอเนื่องจากweakmap.get(new String('any possible key that has ever existed or ever will exist'))จะเป็นเช่นนั้น เสมอ ไม่มีประโยชน์. ลงคะแนน! undefined
user3338098

-5

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

ECMAScript ใช้การรวบรวมขยะอัตโนมัติ ข้อกำหนดไม่ได้กำหนดรายละเอียดปล่อยให้ผู้ใช้งานต้องคัดแยกและการนำไปใช้งานบางอย่างเป็นที่ทราบกันดีว่ามีลำดับความสำคัญต่ำมากสำหรับการดำเนินการรวบรวมขยะ แต่แนวคิดทั่วไปก็คือหากวัตถุไม่สามารถอ้างอิงได้ (โดยไม่มีการอ้างอิงที่เหลืออยู่ที่เหลืออยู่เพื่อให้สามารถเรียกใช้โค้ดได้) มันจะพร้อมใช้งานสำหรับการรวบรวมขยะและในอนาคตบางจุดจะถูกทำลายและทรัพยากรใด ๆ ที่ถูกใช้อย่างอิสระและถูกส่งคืน ไปยังระบบเพื่อนำกลับมาใช้ใหม่

โดยปกติจะเป็นกรณีนี้เมื่อออกจากบริบทการดำเนินการ โครงสร้างห่วงโซ่ขอบเขตอ็อบเจ็กต์การเปิดใช้งาน / ตัวแปรและอ็อบเจ็กต์ใด ๆ ที่สร้างขึ้นภายในบริบทการดำเนินการรวมถึงอ็อบเจ็กต์ฟังก์ชันจะไม่สามารถเข้าถึงได้อีกต่อไปและจะพร้อมใช้งานสำหรับการรวบรวมขยะ

ความหมายไม่มีคนอ่อนแอเท่านั้นที่ไม่มีอีกต่อไป


10
การหลีกเลี่ยงรอบการอ้างอิงไม่ใช่เหตุผลเดียวที่จะใช้การอ้างอิงที่อ่อนแอ มีประโยชน์มากสำหรับการรวม / แคชอินสแตนซ์วัตถุและอื่น ๆ
ปุย

คำจำกัดความของ WeakReference ไม่ใช่คำถาม ตามที่เห็นด้วยกับความคิดเห็นด้านบน
Yuri Yaryshev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.