Элементы Dom не удаляются сборщиком мусора при отсоединении родительского dom цели события из слушателя события - PullRequest
1 голос
/ 04 ноября 2019

Вопрос 1: Почему отдельные элементы dom не собираются сборщиком мусора в следующем скрипте

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>button {padding: 5px 10px;float: left;margin: 10px 5px;background-color: #4653eb;color: #fff;font-weight: bold;cursor: pointer;border: none;outline: none;}button:hover {background-color: #208c2c;}span {float:left;margin-right:2px}</style>
</head>
<body>
    <button id="show-btn">Show</button>
    <div id="container"></div>
    <script src="js.js"></script>
</body>
</html>
// js.js
"use strict";
(function () {

    class Test {
        constructor(outerDom) {
            this._container = null;
            //this.onClick = null;
            this._init(outerDom);
        }

        _init(outerDom) {
            const container = document.createElement('div');

            const clearButton = container.appendChild(document.createElement('button'));
            clearButton.id = 'clear-btn';
            clearButton.textContent = 'Clear';

            //this.onClick = this._removeDomsOnClick.bind(this);
            //clearButton.addEventListener('click', this.onClick);
            clearButton.addEventListener('click', this._removeDomsOnClick.bind(this));

            for (var i = 0; i < 2000; i++) {
                container.appendChild(document.createElement('span')).textContent = 'text inside span';
            };

            outerDom.textContent = '';
            outerDom.appendChild(container);
            this._container = container;
        }

        // Click event handler
        _removeDomsOnClick(e) {
            // Detaching event target from parent
            //e.target.parentNode.removeChild(e.target); // #1

            // Removing event listener
            //e.target.removeEventListener('click', this.onClick);
            //this.onClick = null;

            // Detaching clear button's parent node (It will remove clear button(ie event target) and 2000 spans)
            this._container.parentNode.removeChild(this._container);

            // Not needed(AFAIK). But making sure no reference kept.
            this._container = null;
        }
    }

    document.getElementById('show-btn').addEventListener('click', function () {
        // Not keeping any refernece to newly created instance
        new Test(document.getElementById('container'));
    });

}());

При нажатии button#show-btn создается и прикрепляетсяdom, который содержит button#clear-btn и 2000 span элементов.

При нажатии на button#clear-btn он отсоединит ранее добавленные dom (который содержит button#clear-btn (то есть e.target) и 2000span элементов).

Но эти отсоединенные doms не являются сборщиком мусора (если только сначала не отсоединить button#clear-btn (то есть e.target) от его родителя). Я не вижу никаких ссылок на эти doms в сценарии. Даже если event имеет ссылку на target, path и т. Д., Я ожидаю, что он завершит сборку мусора после завершения события click.


Снимки кучи и временные шкалы распределения

1
Страница только что загружена.
button#clear-btn и spanэлементы еще не созданы.
куча: 1

2
После нажатия button#show-btn
Родитель dom, содержащий button#clear-btn и 2000 span элементы созданы и прикреплены к видимым dom
50KB назначенная память
куча: 2
временная шкала: 2

3a
После нажатия button#clear-btn.
Ранее созданный родительский элемент dom, содержащий элементы button#clear-btn (т.е. e.target) и 2000 span, отсоединяется от видимых dom. Но они не являются сборщиком мусора .
50KB память не освобождается.
куча: 3a
временная шкала: 3a

3b
Примечание: Первый button#clear-btn (то есть e.target) отсоединено от родителя dom (раскомментируйте строку # 1).

После нажатия button#clear-btn.
Ранее созданный родительский элемент dom, содержащий button#clear-btn (т.е. *Элементы 1101 *) и 2000 span отсоединены от видимых dom. Они сборщик мусора .
50KB память уменьшена до 10KB.
куча: 3b
сроки: 3b

Вопрос 2: Даже в 3bпочему 10KB не освобождается?
Почему MouseEvent объект остается в памяти. И вот его родители UIEvent, Event и т. Д. globalThis in Window держат его. Что это такое? Зачем хранить ссылку?
И что такое this in system?
Временная шкала: 3bExpanded
(Ответ на вопрос 1 также может быть ответом на это)

Вопрос 3: В heap:1 почему есть 6 HTMLBodyElement и 4 CanvasRenderingContex2D и 7 HTMLDocument и в heap:2 почему 9 HTMLDivElement
При перезагрузке страницы,иногда эти цифры увеличиваются (26 HTMLBodyElement ...?). Я пытался Empty Cache and Hard Reload. Но без разницы. Если открыть в новой вкладке вместо перезагрузки, они вернутся к нормальному.



В 3a я попытался удалить приемник событий из button#clear-btn перед отсоединениемparent dom (Проверьте комментарии в файле js). Но без разницы.
Я попробовал форсировать collect garbage вариант. Но отдельные домены не собираются.
Консоль пуста.
Точки останова не установлены.

Chrome 78.0.3904.87 Chrome Canary 80.0.3959.0 Incognito Mode with no extensions

...