Циркулярная ссылка в подсчете ссылок Javascript

В книге Николая Закаса он объясняет проблему циклического обращения при использовании подсчета ссылок для сбора мусора в Javascript. Он использует следующий пример:

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

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

объясняя, что у двух объектов никогда не будет выделенной им памяти, поскольку у них есть две ссылки на них внутри функции. Я хотел бы прояснить, как это работает.

Ясно, что для каждого объекта есть две ссылки. Первый объект имеет как objectA, так и objectB.anotherObject, указывающие на него. Таким образом, подсчет ссылок для каждого объекта равен 2. Но что происходит, когда функция выйдет? Это не описано в книге. Он говорит, что счетчик ссылок уменьшается, всякий раз, когда ссылка на значение перезаписывается другим значением. Я думаю, это означает:

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). 

}

Но что происходит, когда функция выходит? Насколько я понимаю, оба objectA и objectB и их соответствующие свойства, которые ссылаются друг на друга, будут уничтожены, и, следовательно, счетчики ссылок на два объекта будут уменьшены на 2. Я не вижу "круглую ссылку" проблема ", о которой говорит Закас. Может ли кто-нибудь объяснить, что он пытается сказать?

Ответ 1

Насколько я понимаю, как objectA, так и objectB и их соответствующие свойства, которые ссылаются друг на друга, будут уничтожены.

Нет. Локальные переменные objectA и objectB будут уничтожены (потому что область функций заканчивается, и никакие замыкания не ссылаются на эти переменные). Это означает, что подсчет ссылок в объектах, на которые ссылаются переменные, каждый получает декремент на 1.

Если счетчик ссылок на объекты равен 0, объект будет уничтожен, а все остальные ссылки, которые он ссылается, уменьшат их количество. Но подсчет объектов все равно 1 каждый - они все еще ссылаются друг на друга - и ничто не уничтожается.

Ответ 2

"Проблема" с подсчетом ссылок и "круговой" ссылкой возникает, когда выделенные объекты содержат ссылки на другие объекты, но в противном случае они не связаны с активными выделениями. То есть, есть клики на общем контрольном графике элементов, которые неактивны, но которые, тем не менее, содержат ссылки на другие неактивные элементы.

В вашем примере кода, когда эта функция выходит, активных ссылок на два выделенных объекта нет, но объекты ссылаются друг на друга, поэтому счетчики ссылок не равны 0. Локальные переменные objectA и objectB исчезнут на выход функции (потому что закрытие само по себе является мусором, в этой точке), но внутренние ссылки на объекты сохраняют их отсчеты ссылок больше нуля.

Это не неразрешимая проблема, но это усложняет простой подход подсчета ссылок как метод сбора мусора.

Обратите внимание, что нет правила или спецификации, которые настаивают на реализации JavaScript, используя какой-либо конкретный метод сбора мусора.