Как выгрузить JavaScript из HTML? - PullRequest
19 голосов
/ 06 декабря 2010

Как я могу выгрузить ресурс JavaScript со всеми его определенными объектами из DOM?

Я разрабатываю простой фреймворк, который позволяет загружать фрагменты HTML в «основной» HTML. Каждый фрагмент является автономным и может содержать ссылки на дополнительные файлы JS и CSS. Ресурсы JS и CSS анализируются и динамически добавляются в html. Когда фрагмент удаляется / заменяется из DOM, я хочу удалить его JS и CSS.

Если я удалю элемент script в примере ниже, функции, определенные в page1.js, все еще будут доступны.

<html>
  <head>
    <script src="page1.js" type="text/javascript"></script>
  </head>
<body>
...

Есть ли способ выгрузки объектов page1.js из DOM?

========= Используемый мной тестовый код =======

Я попробовал совет, который получил в комментариях ниже; удалить добавленные объекты с помощью функции очистки - но даже это не удается. Источники, которые я использовал для тестирования:

<html>
<head>
<script type="text/javascript">
    function loadJSFile(){
        var scriptTag = document.createElement("script");
        scriptTag.setAttribute("type", "text/javascript");
        scriptTag.setAttribute("src", "simple.js");

        var head = document.getElementsByTagName("head")[0];
        head.appendChild(scriptTag);
    }

    function unloadJSFile(){            
        delete window.foo;
        delete window.cleanup;
        alert("cleanedup. typeof window.foo is " + (typeof window.foo));
    }
</script>
</head>
<body>

  Hello JavaScript Delete

  <br/>
  <button onclick="loadJSFile();">Click to load JS</button>
  <br/>
  <button onclick="foo();">call foo()</button>
  <br/>
  <button onclick="unloadJSFile();">Click to unload JS</button>

</body>
</html>

simple.js источник:

var foo = function(){
    alert("hello from foo");
}

Ответы [ 7 ]

14 голосов
/ 06 декабря 2010

Этого нельзя сделать.

При выполнении скрипта определения функций добавляются в глобальный объект window.К функции могут быть прикреплены отладочные символы, которые указывают, откуда эта функция пришла, но эта информация недоступна для сценариев.

О единственном способе достижения чего-либо подобного является создание псевдо-пространства именв сценарии, а затем выбросить все пространство имен, когда вы закончите с ним.Однако этот вопрос намекает мне на то, что вы пытаетесь сделать что-то неправильно.Возможно, разработка вашего сценария поможет нам предложить альтернативные решения.

6 голосов
/ 06 декабря 2010

Нет, это невозможно. Вы можете создать простую функцию очистки, которая удаляет все переменные, которые были определены в этом файле:

var foo = 'bar';
var cleanup = function () {
    delete window.foo;
    delete window.cleanup;
};

// unload all resources
cleanup();

Другой подход заключается в использовании модульной структуры объектов для ваших фрагментов, которые убираются за собой. Это требует немного больших накладных расходов, но, вероятно, того стоит, так как делает код намного проще для чтения и обслуживания:

// creates the object using the second parameter as prototype.
// .create() is used as constructor
GlobalModuleHandlerThingy.addModule('my_module', {
    create: function () {
        this.foo = 'bar';
        return this;
    },
    foo: null,
    destroy: function () {
        // unload events, etc.
    }
});

GlobalModuleHandlerThingy.getModule('my_module').foo; // => bar
GlobalModuleHandlerThingy.unloadModule('my_module'); // calls .destroy() on the module and removes it.
4 голосов
/ 06 декабря 2010

возможно, вам следует рассмотреть возможность условной загрузки, а не условной выгрузки ...

2 голосов
/ 06 декабря 2010

Если вам нужно выгрузить определенный объект, это довольно просто: просто установите его на {}

т.е.: myobj = {};

Так что, если вы знаете, какие объекты создаются в конкретном включении, это совсем не сложно.

С другой стороны, если вы не знаете, какие объекты создаются в конкретном включении, нет механизма, который нужно выяснить - вы не можете попросить Javascript рассказать вам, что было определено в определенном включении.

Однако я бы сказал, что если вы не знаете, какие объекты загружаются в конкретный файл javascript, вы, вероятно, не оказываете никакой помощи при его загрузке (вы всегда должны иметь разумное представление о том, что делает код на вашем сайте) или при попытке выгрузить его вручную (если вы не знаете, что он делает, это означает, что его включает в себя третье лицо, что означает, что удаление его вручную может привести к поломке).

0 голосов
/ 07 августа 2018

вы можете сделать их = ноль

    function fnc1 (){

    }

    window.fnc1  = null
    //or
    window["fnc1"]  = null
0 голосов
/ 22 июля 2017

Я придумал трюк для этого.Мне было интересно здесь найти ответ на этот вопрос, и я просто осознал идеальный трюк, чтобы сделать это, не пытаясь загрузить Java Script.Вам нужно только создать глобальную переменную, например currentPage, в java-скрипте main страницы, а при загрузке страницы назначить имя страницы currentPage.затем в каждом другом файле .js используйте $('document').ajaxComplete() вместо $('document').ready(), добавив оператор if в качестве первой строки внутри каждой функции $('document').ajaxComplete().установите для проверки currentPage переменную, равную новому имени страницы.добавьте все остальные события внутри оператора if.Я не очень хорошо знаю английский, поэтому проверь мой код.И это мой первый ответ, поэтому извините, если я совершил несколько ошибок.

main.html

<body>
    <div id='container></div>
    <button id="load1">
    <button id="load1">
</body>

main.js

var currentPage = "";

$(document).ready(function () {
    $('#load1').click(function () {
        loadSource('page1', 'body');
    });
    $('#load2').click(function () {
        loadSource('page2', 'body');
    });
});

function loadSource( page, element){
    currentPage = page;
    $('#container').load('views/' + page + '.php', element);
    $.getScript('js/' + page + '.js');
    $('#css').prop('disabled', true).remove();
    $('head').append('<link rel="stylesheet" href="css/' + page + '.css" type="text/css" />');
}

все скрипты и стили моих страниц находятся в отдельных папках, js, css.

page1.html

<body>
    <button id="test1">
    <button id="test2">
</body>

page1.js

$(document).ajaxComplete(function () {
    if(currentPage == 'page1'){
        /*$('#test1').click(function () {
            console.log('page1');
        });*/
        $('#test2').click(function () {
            console.log('page1');
        });
    }
});

page2.html

<body>
    <button id="test1">
    <button id="test2">
</body>

page2.js

$(document).ajaxComplete(function () {
    if(currentPage == 'page2'){
        $('#test1').click(function () {
            console.log('page2');
        });
        /*$('#test2').click(function () {
            console.log('page2');
        });*/
    }
});

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

0 голосов
/ 05 августа 2014

Сам искал что-то подобное и думал, что опубликую свои выводы

  1. Оберните ваши вещи в глобальном пространстве имен в файл js, чтобы их можно было легко удалить, т.е. var stuff = {blabla: 1, method: function () {}};

  2. Когда вам нужно от него избавиться, просто установите вещи = {}, или ноль, даже

  3. Удалить тег скрипта со страницы

*** Если вы используете requirejs - требует, чтобы js удалил определение для принудительной перезагрузки

Примечание: если вы не ссылаетесь на модули внутри пространства имен из других источников, все будет собираться GC, и вы готовы к работе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...