ใน Javascript มีวิธีสร้างโคลนแบบคัดลอกเมื่อเขียนของวัตถุหรือไม่?

ปัญหา: ฉันกำลังเขียนฟังก์ชันที่ส่งคืนวัตถุจาวาสคริปต์ธรรมดาขนาดใหญ่อีกครั้ง วัตถุต้นฉบับไม่ควรได้รับการแก้ไขโดยผู้โทร ปัจจุบันมีผู้โทรหลายร้อยคนเรียกใช้ฟังก์ชันนี้

วิธีแก้ปัญหาบางอย่าง:

  • ส่งคืนสำเนาวัตถุในเชิงลึก นี่คือวิธีแก้ปัญหาปัจจุบัน สิ่งนี้ไม่ดีเนื่องจาก (a) วัตถุมีขนาดใหญ่มากและ (b) 90% ของเวลาที่โคลนนั้นไม่จำเป็นเนื่องจากผู้เรียกส่วนใหญ่ไม่ได้แก้ไขค่า
  • ส่งคืนการอ้างอิงไปยังวัตถุ สิ่งนี้ไม่ดีเพราะผู้โทรจะสามารถแก้ไขวัตถุดั้งเดิมซึ่งฉันไม่ต้องการได้
  • ส่งกลับข้อมูลอ้างอิงด้วย Object.freeze หรือสิ่งที่คล้ายกัน สิ่งนี้อาจได้ผลหากฉันรับประกันได้ว่าผู้โทรจะไม่พยายามแก้ไขค่าที่ส่งคืน แต่ฉันไม่สามารถรับประกันเรื่องนี้ได้ ขอย้ำอีกครั้งว่าฟังก์ชันนี้ถูกเรียกใช้โดยผู้โทรหลายร้อยคน และหลายคนได้แก้ไขค่า (โคลนของ) แล้ว

สิ่งที่ฉันต้องการคือโซลูชันการคัดลอกเมื่อเขียนที่มีคุณสมบัติสองประการต่อไปนี้:

  1. ค่าที่ส่งคืนของฟังก์ชันคือ การอ้างอิง ไปยังวัตถุต้นฉบับจนกว่าค่าจะได้รับการแก้ไข
  2. หลังจากแก้ไขค่าแล้ว ค่าจะกลายเป็น โคลนระดับลึก ของออบเจ็กต์ต้นฉบับ

ฉันทำการทดสอบบางอย่างและสามารถใช้งานได้โดยใช้ Javascript Proxy. เพียงดักจับการดำเนินการทั้งหมดที่ปรับเปลี่ยนเป้าหมาย (เช่น set, deleteProperty, defineProperty ฯลฯ) เพื่อรับฟังการเปลี่ยนแปลง จากนั้นดักจับบน get เพื่อส่งคืนการอ้างอิงหากไม่มีการเปลี่ยนแปลง และส่งคืนโคลนหากมีการเปลี่ยนแปลง พร็อกซีจะต้องเป็นพร็อกซีเชิงลึกเพื่อรับฟังการเปลี่ยนแปลงในคุณสมบัติที่ซ้อนกัน

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


person Some Guy    schedule 15.02.2020    source แหล่งที่มา
comment
ดูเหมือนว่า cow คือสิ่งที่คุณต้องการ npmjs.com/package/cow   -  person artanik    schedule 15.02.2020
comment
@artanik อืม...นี่ดูมีแนวโน้มดี ขอบคุณ!   -  person Some Guy    schedule 16.02.2020
comment
คุณได้ลองใช้แพ็คเกจ immer แล้วหรือยัง   -  person Aswin    schedule 18.10.2020


คำตอบ (1)


ไลบรารี immer ทำสิ่งที่คุณอธิบายทุกประการ - การใช้งาน COW โดยใช้พร็อกซี JavaScript ดูเอกสารที่นี่: https://immerjs.github.io/immer/

person Nir    schedule 08.05.2021