Как собрать внешнюю загрузку Javascript? - PullRequest
0 голосов
/ 05 июля 2019

Есть ли преимущества или проблемы для onload = null после загрузки внешнего скрипта?
Выгода может быть в том, что GC освобождает память?

После редактирования сома должен быть рассмотрен следующий код.
Смотрите комментарии.

function fetch(src, callback, fail) {
    let s = document.head.appendChild(document.createElement('script'));
    s.type = "text/javascript";
    s.src = src;
    s.onload = function() {
        callback()
        s.onload = null; //useful?
        s = null; //or maybe this?
    }
    s.onerror = fail
}

Я не знаю, как это делает Javascript или если он бесплатен для браузера, делайте так, как он хочет, но в случае, если в закрытии остается много больших скриптов, после того, как он вставлен в DOM, его следует удалить из Garbage Сборщик вручную, если это не сделано автоматически (для этого лучше всего обратиться к w3c, чтобы знать, что это делают все совместимые браузеры)

Ответы [ 2 ]

1 голос
/ 05 июля 2019

Да, для GC полезно установить свойства на null.При этом удаляются ссылки из элемента (который содержится в DOM) на функцию-обработчик, и, учитывая, что это, вероятно, единственная ссылка на функцию, она делает функцию пригодной для сбора.Однако, если функция не является замыканием по переменным, сохраняющим большой блок памяти, маловероятно, что это окажет большое влияние.

Возможно, вы также захотите удалить элемент s из DOM вобратный вызов, что делает его также сборщиком мусора.

0 голосов
/ 06 июля 2019

Да, s.onload = null полезно и будет собирать мусор!

С 2019 года явный или программный запуск сбора мусора в JavaScript невозможен.Это означает, что он собирает, когда захочет.
Хотя есть случаи , когда установка на null может сделать GC раньше (но не инициировать это).

С 2012 года все современные браузеры поставляют сборщик мусора .
Он работает по принципу достижимости :

Каждый объект, недоступный из глобального контекста, удаляется

Периодически mark-and-sweep обнаруживает и удаляет объект, когда каждая переменная, в которой он находится, является возвращено, переназначено или установлено на ноль .Кроме того, в настоящее время нет необходимости рекурсивно устанавливать значение NULL для содержимого, которое не доступно ни для одной переменной - оно все равно собирается mark-and-sweep .

А теперьрассматриваемый код ...

В первой строке мы видим, что s и дочерний элемент document.head указывают на то же document.createElement('script').Когда функция возвращается и замыкание удаляется из стека вызовов, ее объявленная переменная s также удаляется.Значение, на которое ссылается s, не является сборщиком мусора, потому что оно все еще доступно через document.

Итак. Нет необходимости в s = null, так как указатель очищается в любом случае, когда переменная удаляется, но естьstill является ссылкой на свойство сценариев onload, поскольку <script onload> является потомком document.head в DOM, достижимом из window!

Содержимое callback может быть доступно, но здесь не может быть и речи.

Что если браузер достаточно умен, чтобы установить s.onload = null внутри?Мы опробуем его, сначала закомментировав его в первом фрагменте, и раскомментировав его во втором фрагменте ...

function fetch(src, callback, fail) {
    let s = document.head.appendChild(document.createElement('script'));
    s.type = "text/javascript";
    s.src = src;
    s.onload = function() {
        callback()
        //s.onload = null; //useful?
    }
    s.onerror = fail
}

fetch("https://stackoverflow.com", 
       () => {console.log("Execute onload");}, 
       () => {console.log("File not found");})

setTimeout(() => {
    console.log(document.head.lastChild.onload)
},1000)

Найденный файл выполняется с ошибкой, поскольку он не является Javascript.
onload выполняется, но не удаляется.Код отображается в журнале!
Это подтверждает, что следует использовать строку с s.onload = null , например:

function fetch(src, callback, fail) {
    let s = document.head.appendChild(document.createElement('script'));
    s.type = "text/javascript";
    s.src = src;
    s.onload = function() {
        callback()
        s.onload = null; //useful!
    }
    s.onerror = fail
}

fetch("https://stackoverflow.com", 
       () => {console.log("Execute onload");}, 
       () => {console.log("File not found");})

setTimeout(() => {
    console.log(document.head.lastChild.onload)
},1000)
...