Circular reference = 2 object tham chiếu lẫn nhau (A→B, B→A).
Vấn đề lịch sử
Trên IE6/7 (GC reference-counting): circular reference khiến bộ nhớ không giải phóng được → memory leak.
Hiện tại
GC hiện đại (mark-and-sweep, generational) xử lý chu trình hoàn hảo — không còn leak.
Vẫn xấu vì thiết kế (code smell)
- Tight coupling: Thay đổi A buộc phải sửa B, ngược lại.
- Khó test, khó reuse: Không thể tách biệt test từng object.
- Khó serialize:
JSON.stringify()sẽ lỗi "Converting circular structure to JSON".
Ví dụ
let dog = new Dog(); let person = new Person(); dog.owner = person; person.pet = dog; // circular
Giải pháp
- Giữ 1 chiều (owner hoặc pet), dùng ID/map tra ngược.
- Dùng
WeakMapcho mapping ngược (không cản GC). - Nếu bắt buộc 2 chiều — chấp nhận, nhưng document rõ ràng.