นี่คือตัวอย่างของโครงสร้างข้อมูลที่มีการอ้างอิงแบบวนซ้ำ:
function makeToolshed(){
var nut = {name: 'nut'}, bolt = {name: 'bolt'};
nut.needs = bolt; bolt.needs = nut;
return { nut: nut, bolt: bolt };
}
เมื่อคุณต้องการเก็บการอ้างอิงแบบวนรอบ (คืนพวกเขาเมื่อคุณหมดความอดทนแทนที่จะเป็น "พวกนิก") คุณมี 2 ทางเลือกซึ่งฉันจะเปรียบเทียบที่นี่ อย่างแรกคือcycle.jsของ Douglas Crockford ส่วนที่สองคือแพ็คเกจไซบีเรียของฉัน ทั้งสองทำงานโดย "decycling" วัตถุแรกคือการสร้างวัตถุอื่น (โดยไม่มีการอ้างอิงแบบวนซ้ำ) "ที่มีข้อมูลเดียวกัน"
Mr. Crockford ไปก่อน:
JSON.decycle(makeToolshed())
อย่างที่คุณเห็นโครงสร้างซ้อนของ JSON นั้นยังคงอยู่ แต่มีสิ่งใหม่ซึ่งเป็นวัตถุที่มี$ref
คุณสมบัติพิเศษ เรามาดูกันว่ามันทำงานอย่างไร
root = makeToolshed();
[root.bolt === root.nut.needs, root.nut.needs.needs === root.nut]; // retutrns [true,true]
เครื่องหมายดอลลาร์หมายถึงรูต .bolt
ต้อง$ref
บอกเราว่า.bolt
เป็นวัตถุ "เห็นแล้ว" และค่าของคุณสมบัติพิเศษนั้น (ที่นี่สตริง $ ["nut"] ["ต้องการ"]) บอกเราว่าที่ใดดูก่อน===
ข้างบน เช่นเดียวกันสำหรับวินาที$ref
และวินาที===
ข้างต้น
ลองใช้การทดสอบความเท่าเทียมกันอย่างลึกซึ้งที่เหมาะสม (คือdeepGraphEqual
ฟังก์ชั่นของ Anders Kaseorg จากคำตอบที่ได้รับการยอมรับสำหรับคำถามนี้ ) เพื่อดูว่าการโคลนนิ่งทำงานหรือไม่
root = makeToolshed();
clone = JSON.retrocycle(JSON.decycle(root));
deepGraphEqual(root, clone) // true
serialized = JSON.stringify(JSON.decycle(root));
clone2 = JSON.retrocycle(JSON.parse(serialized));
deepGraphEqual(root, clone2); // true
ตอนนี้ไซบีเรีย:
JSON.Siberia.forestify(makeToolshed())
ไซบีเรียไม่พยายามเลียนแบบ JSON แบบ "คลาสสิค" ไม่มีโครงสร้างซ้อนกัน กราฟวัตถุอธิบายไว้ในลักษณะ "แบน" แต่ละโหนดของกราฟวัตถุถูกเปลี่ยนเป็นต้นไม้แบน (รายการคู่ค่าคีย์ธรรมดาที่มีค่าจำนวนเต็มเท่านั้น) ซึ่งเป็นรายการใน.forest.
ศูนย์ดัชนีเราพบวัตถุรากที่ดัชนีที่สูงกว่าเราจะพบโหนดอื่น ๆ ของ กราฟวัตถุและค่าลบ (ของคีย์บางต้นของฟอเรสต์) ชี้ไปที่atoms
อาร์เรย์ (ซึ่งพิมพ์ผ่านอาร์เรย์ประเภท แต่เราจะข้ามรายละเอียดการพิมพ์ที่นี่) forest.length
ทุกโหนดขั้วอยู่ในตารางอะตอมทุกโหนดที่ไม่ใช่ขั้วอยู่ในตารางป่าและคุณสามารถดูได้ทันทีว่าหลายโหนดกราฟวัตถุมีคือ ลองทดสอบว่ามันใช้งานได้ไหม:
root = makeToolshed();
clone = JSON.Siberia.unforestify(JSON.Siberia.forestify(root));
deepGraphEqual(root, clone); // true
serialized = JSON.Siberia.stringify(JSON.Siberia.forestify(root));
clone2 = JSON.Siberia.unforestify(JSON.Siberia.unstringify(serialized));
deepGraphEqual(root, clone2); // true
การเปรียบเทียบ
จะเพิ่มส่วนในภายหลัง