2017-09-18 33 views
12

Trong sách của Nicholas Zakas, ông giải thích vấn đề tham chiếu vòng tròn khi sử dụng tính toán tham chiếu để thu thập rác trong Javascript. Anh ấy sử dụng ví dụ sau:Tham chiếu tham chiếu trong số tham chiếu Javascript

function problem(){ 
    var objectA = new Object(); 
    var objectB = new Object(); 

    objectA.someOtherObject = objectB; 
    objectB.anotherObject = objectA; 
} 

giải thích rằng hai đối tượng sẽ không bao giờ có bộ nhớ được phân bổ cho chúng giải phóng vì chúng có hai tham chiếu đến chúng bên trong hàm. Tôi muốn một số làm rõ cách thức hoạt động của nó.

Rõ ràng, có hai tham chiếu đến từng đối tượng. Đối tượng đầu tiên có cả hai ký tự objectAobjectB.anotherObject trỏ đến nó. Vì vậy, số lượng tham chiếu cho mỗi đối tượng là 2. Nhưng điều gì sẽ xảy ra khi chức năng được thoát? Điều này không thực sự được mô tả trong cuốn sách. Ông nói rằng số lượng tham chiếu được giảm đi bất cứ khi nào một tham chiếu đến giá trị được ghi đè bằng một giá trị khác. Tôi nghĩ điều này có nghĩa là:

function problem(){ 
    var objectA = new Object(); 
    var objectB = new Object(); 

    objectA.someOtherObject = objectB; 
    objectB.anotherObject = objectA; 
    objectA.someOtherObject = objectA; //<-- that if I were to do this, 
             //the reference count of the first object (A) 
             //would become 3, and 1 for the second object (B). 

} 

Nhưng điều gì sẽ xảy ra khi chức năng thoát? Theo tôi hiểu, cả hai số objectAobjectB và các thuộc tính tương ứng tham chiếu lẫn nhau sẽ bị hủy và do đó, số lượng tham chiếu của hai đối tượng sẽ bị giảm đi 2. Tôi không thấy "vấn đề tham chiếu vòng tròn" mà Zakas cuộc đàm phán về. Ai đó có thể giải thích những gì anh ta đang cố nói?

Trả lời

11

Theo như tôi hiểu, cả objectA và objectB và thuộc tính tương ứng của chúng tham chiếu lẫn nhau sẽ bị hủy.

số Các biến địa phươngobjectAobjectB sẽ bị phá hủy (vì phạm vi chức năng kết thúc và không đóng cửa tham khảo các biến). Điều đó có nghĩa là số lượng tham chiếu trong các đối tượng được tham chiếu bởi các biến được giảm xuống bởi .

Nếu số tham chiếu của đối tượng là 0, đối tượng sẽ bị hủy và tất cả những thứ khác mà nó tham chiếu sẽ bị giảm số lượng của chúng. Nhưng số lượng của các đối tượng vẫn là 1 mỗi - chúng vẫn tham chiếu lẫn nhau - và không có gì bị phá hủy.

+0

Có triển khai nào vẫn dựa trên việc tính tham chiếu không? Theo https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management, các đối tượng này * sẽ bị * phá hủy với tất cả các triển khai hiện đại. – rici

+0

@rici Không, tham khảo đếm - ít nhất là ở dạng ngây thơ của nó - không được sử dụng chính xác vì sự thiếu hụt này và [cần cải tiến] (https://en.wikipedia.org/wiki/Reference_counting#Dealing_with_reference_cycles). Như MDN nói, tất cả các công cụ hiện đại đều sử dụng một số triển khai đánh dấu và quét. Tuy nhiên, việc đếm tham chiếu vẫn có thể được áp dụng cho các cấu trúc cục bộ cụ thể được biết là không có hoặc không theo chu kỳ, nơi nó có thể hoạt động tốt hơn vì tính đơn giản của nó. – Bergi

+1

vâng, đó là những gì tôi nghĩ. Tôi cho rằng cuốn sách được đề cập đến trong OP có phần ngày tháng, vì tôi tin rằng các phiên bản đầu tiên của MSIE bị vấn đề này. Nhưng ấn tượng của tôi là việc triển khai ES hiện đại sẽ thu thập chính xác cả hai đối tượng trong ví dụ này. Tôi hiểu rằng câu hỏi là giải thích vấn đề với các tham chiếu vòng tròn trong một môi trường được tính toán lại nhưng chắc chắn điều đáng nói đến trong câu trả lời là vấn đề không còn tồn tại trong thực tế; không cần phải tự phá vỡ chu kỳ tham chiếu, trái với lời khuyên bạn vẫn sẽ tìm thấy trôi nổi xung quanh. – rici

10

"Sự cố" có tính tham chiếu và tham chiếu "vòng tròn" xuất hiện khi đối tượng được phân bổ chứa tham chiếu đến các đối tượng khác, nhưng nếu không được phân bổ bằng phân bổ hoạt động. Đó là, có những dòng trong đồ thị tham chiếu tổng thể của các mục không hoạt động nhưng nó chứa tham chiếu đến các mục không hoạt động khác.

Trong mã ví dụ của bạn, khi chức năng mà thoát không có tài liệu tham khảo tích cực với hai đối tượng được phân bổ, nhưng các đối tượng tham khảo lẫn nhau nên đếm tài liệu tham khảo không phải là 0. Các biến địa phương objectAobjectB sẽ biến mất tại thoát khỏi hàm (vì đóng cửa chính nó là rác, tại thời điểm đó), nhưng tham chiếu bên trong các đối tượng giữ cho số lượng tham chiếu của chúng lớn hơn 0.

Nó không phải là một vấn đề không thể giải quyết được, nhưng nó làm phức tạp cách tiếp cận khác đơn giản tham khảo tính như một kỹ thuật thu gom rác thải.

Lưu ý rằng không có quy tắc hoặc đặc tả nào khẳng định việc triển khai JavaScript sử dụng bất kỳ kỹ thuật thu thập rác cụ thể nào.

+0

Cảm ơn câu trả lời của bạn.Một câu hỏi nữa: Nếu 'objectA' và' objectB' bị hủy, thì các thuộc tính cơ bản của chúng không bị phá hủy như thế nào? Tôi có nhầm lẫn giữa các biến cục bộ (có tham chiếu không?) Với các đối tượng thực trong bộ nhớ? – Sahand

+2

Các biến * 'objectA' và' objectB' bị hủy. Hãy suy nghĩ về các biến cục bộ như các thuộc tính của một đối tượng "bóng" được tạo ra khi hàm được gọi. Khi hàm thoát, đối tượng đó không có tham chiếu đến nó để các thuộc tính của nó biến mất. Tất cả điều đó có nghĩa là các đối tượng * tham chiếu * bởi các biến cục bộ có số lượng tham chiếu của chúng giảm đi 1. – Pointy

+2

"có các dòng ..." - ý của bạn là "chu kỳ", thay vào đó? Các đồ thị (đồ thị hoàn chỉnh) hiển thị vấn đề, nhưng chúng không cần thiết cho nó. – chi

Các vấn đề liên quan