Правильно, но я спрашиваю: а что, если у меня есть контроль над first.js, а не second.js?

емного странный случай, но у меня есть свои причины:

Я хотел бы иметь возможность написать

<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>

в моей разметке и, используя код вfirst.jsпредотвратить или задержать исполнениеsecond.js, Это возможно в любом браузере? Что делать, если содержимоеfirst.js встроены? (Если это поможет, предположим, что второй тег сценария имеетid атрибутов.)

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

Решение должно быть полностью внутриfirst.js, Все, что требует изменения исходного HTML-кода страницы илиsecond.jsне допускается.Этоявляется приемлемо для загрузкиsecond.js через Ajax и выполнить его с помощьюeval, Это легкая часть. Трудной частью является предотвращение немедленного исполненияsecond.js.Предположим, что выне знаю Что вsecond.js, Таким образом, вы не можете просто заменить каждую глобальную функцию, вызываемуюsecond.js с неоперативной функцией. (Кроме того, это почти наверняка приведет к ошибкам.)

Если вы знаете решение, которое работает в некоторых браузерах, но не в других, я бы хотел услышать его.

пример: Чтобы сделать это немного более конкретным, скажем, что код

<script type="text/javascript">
  function func() {
    window.meaningOfLife = 42;
    window.loadSecond();
  };
  setTimeout(func, 10);
</script>

предшествует двумscript включает в себя, и чтоsecond.js содержит строку

if (window.meaningOfLife !== 42) {throw new Error();}

first.js должен быть в состоянии предотвратить эту ошибку, задерживаяsecond.js от выполнения доwindow.loadSecond это запустить. (Предположим, что реализацияwindow.loadSecond также вfirst.js.) Этоне разрешено трогатьwindow.meaningOfLife.

Обновить: Ответ Алохчи отвечает этим требованиям, но только при условии, что появится второй тег сценариянемедленно после первого, с пустым пространством между ними. Если бы кто-то мог продлить свой взлом, чтобы избежать этого требования, не представляя других нежелательных последствий, это было бы удивительно ...

Ответы на вопрос(7)

<script> метки имеют своиконтекст выполнения, что делает практически невозможным вмешиваться друг в друга. Конечно, вы получили (печально)глобальный объект (ссылаетсяwindow в браузерах).

Предотвращение исполненияsecond.js довольно просто:сломать Это! При условии, чтоsecond.js пытается позвонитьdocument.getElementById например:

Рабочий пример взлома jQuery, затем загрузка позже (с зависимостями).
Проверено на:IE 6+, FF 3.6+, Chrome

конец first.js

var execute;

// saving our position
var scripts = document.getElementsByTagName("script");
var i = scripts.length;

// breaking getElementById
var byId = document.getElementById;
document.getElementById = null;

var interval = setInterval(function () {
    if (i != scripts.length) {
      var second = scripts[i];
      // stop polling
      clearInterval(interval);
      // fix getElementById
      document.getElementById = byId;
      // set the delayed callback
      execute = function (onload) {
        var script = document.createElement("script");
        script.src = second.src;
        script.onload = script.onreadystatechange = onload;
        document.getElementsByTagName("head")[0].appendChild(script);
      };
    }
}, 100);

в любое время ты хочешьвыполнить second.js

execute(function(){
   // second.js dependant code goes here...
});

Обратите вниманиеonload параметр дляexecute необязательно.

 gblazex21 янв. 2011 г., 15:51
Хотя я должен также отметить, что сама идея довольно жуткая. :)
 Trevor Burnham21 янв. 2011 г., 17:33
Я до сих пор высказываюсь об этом как о наиболее полном ответе на данный момент - рабочий пример потрясающий. Если бы это могло быть обобщено ...
 Marcel Korpel21 янв. 2011 г., 16:03
Ой! Ужасный хак!
 Trevor Burnham21 янв. 2011 г., 17:29
Есть несколько проблем с этим решением. Для одного (и я должен был быть более ясным в моем первоначальном посте), я хочу решение, которое будет работать, даже если содержаниеsecond.js неизвестны. И 2) если вы сломаете вещи, которыеsecond.js звонки, вы почти наверняка получите ошибки. Я не хочу ошибок. Даже заменаdocument.getElementById с неоперативной функцией может вызвать проблемы, когдаsecond.js пытается что-то сделать с результирующим элементом.
 gblazex21 янв. 2011 г., 18:15
@Trevor - Вероятно, другого пути нет, дело в том, что вы можете остановить выполнение только в случае ошибки. Какого черта тебе это все равно нужно? Если у вас нет разметки и другого файла, вам не следует связываться с ними вообще.

Насколько я знаю, ты не можешь. Если разметка выглядит

<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>

вы не можете получить доступ ко второму элементу скрипта изнутриfirst.js, поскольку он не был добавлен в DOM в момент запуска первого скрипта (даже если вы не назначитеid ко второму элементу). Неважно, является ли кодsecond.js помещается в строку или во внешний файл.

Единственное, что я не понимаю, это твой второй момент. Сначала вы говорите, что не можете контролировать разметку документа, но затем утверждаете, что можно загрузитьsecond.js динамически (с использованием AJAX).

 Marcel Korpel21 янв. 2011 г., 16:01
Почему это отклонено? Я надеюсь, что нет, потому что это не тот ответ, на который надеялся ОП. Пожалуйста, объясни.
 Trevor Burnham21 янв. 2011 г., 17:38
Правильно, я согласен, что это кажется невозможным ... и тем не менее, у galambalazs есть решение, которое работает в некоторых случаях. :) Во-первых, вы не можете контролироватьоригинал разметка документа; вы можете манипулировать им только изfirst.js, Я отвечал на решение dorkitude, которое работает, только если вы опустите оригинал<script src="second.js"> тег.
 Incognito21 янв. 2011 г., 22:48
Это было установлено в прошлой SO (извините, не смог найти) ветке, которую теги <script> оценивают индивидуально, а не все сразу.
 Marcel Korpel22 янв. 2011 г., 12:45
@user: Конечно, но все же вы не можете манипулировать элементами DOM, которые еще не были добавлены.
Решение Вопроса

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

Во-первых, давайте предположим, что HTML выглядит так:

<!DOCTYPE html>
<html>
  <head>
    <title>Test Case</title>
    <meta charset="UTF-8" />
    <script type="text/javascript">
      function func() {
        window.meaningOfLife = 42;
        window.loadSecond();
      };
    </script>
    <script type="text/javascript" src="first.js"></script>
    <script type="text/javascript" src="second.js"></script>
  </head>
  <body>
    <p>Lorem ipsum dolor sit amet ...</p>
    <a href="javascript:func()">Run Func()</a>
  </body>
</html>

Я удалил setTimeout, потому что это может привести к запуску func () до запуска start.js, что приведет к ошибке «loadSecond is notfined». Вместо этого я предоставил ссылку для запуска func ().

Во-вторых, давайте предположим, что second.js выглядит так:

document.body.appendChild(document.createTextNode("second.js has run. "));
if (window.meaningOfLife !== 42) {throw new Error();}

Здесь я только что добавил строку для добавления текста в тело документа, чтобы было легче увидеть, когда фактически выполняется second.js.

Тогда решение для first.js таково:

function loadSecond()
{
    var runSecond = document.createElement("script");
    runSecond.setAttribute("src", "second.js"); 
    document.body.appendChild(runSecond);
}

document.write("<script type='application/x-suppress'>");

Функция loadSecond предназначена для запуска second.js при запуске func ().

Ключом к решению являетсяdocument.write линия. Это будет вводить в HTML<script type='application/x-suppress'> между тегом закрытия скрипта first.js и тегом открытия скрипта second.js.

Парсер увидит это и запустит новый элемент скрипта. Поскольку атрибут type имеет значение, которое не распознается браузером как JavaScript, он не будет пытаться запустить его содержимое. (Таким образом, существует неограниченное количество возможных значений атрибутов типа, которые вы можете использовать здесь, но вы должны включить атрибут типа, так как при его отсутствии браузер будет предполагать, что содержимое сценария является JavaScript.)

Открывающий тег скрипта second.js будет затем проанализирован как текстовое содержимое нового элемента скрипта и не будет выполнен. Наконец, закрывающий тег скрипта second.js будет переопределен, чтобы вместо этого закрыть новый элемент скрипта, что означает, что остальная часть HTML анализируется правильно.

Вы можете увидеть рабочую версию наhttp://www.alohci.net/static/jsprevent/jsprevent.htm

 Tzook22 авг. 2015 г., 14:24
Ты гений. @Alohci
 Trevor Burnham24 янв. 2011 г., 18:46
Они сказали, что это невозможно сделать, но вы сделали это! Хотя я согласен, что это, вероятно, не следует использовать в производстве, оно работает без сбоев во всех браузерах, в которых я его пробовал. Поздравляю, Алохчи, щедрость твоя. :)
 David Tang24 янв. 2011 г., 10:57
@ Ms2ger, это совершенно не имеет отношения к вопросу ... Alohci, хороший ответ!
 Caleb24 янв. 2011 г., 13:13
Это очень неприятный хакерский инстинкт, но, похоже, это лучший выстрел, учитывая отсутствие реального механизма для этого. Любой, кто использует это, должен знать, что это хрупкий и уродливый взлом, который браузеры могут решить уничтожить в любое время. Если это невыполнение сценария действительно критически важно, я предлагаю поработать с первоначальными авторами html и других js-файлов.

first.js, установленvar shouldILoad = true

Затем загрузитьsecond.js сюда:

<script>
    if (shouldILoad) {
        (function() {
            var myscript = document.createElement('script');
            myscript.type = 'text/javascript';
            myscript.src = ('second.js');
            var s = document.getElementById('myscript');
            s.parentNode.insertBefore(myscript, s);
        })();
    }
</script>

(где «myscript» - это идентификатор некоторого элемента, перед которым вы хотите вставить новый элемент Script)

 Kyle Wild21 янв. 2011 г., 20:27
Ах, в этом случае я понятия не имею. Я оставлю свой ответ, так как это все еще полезный метод, если у вас есть такой доступ :)
 Trevor Burnham20 янв. 2011 г., 20:47
Извините, моя первоначальная формулировка могла быть неясной: предположим, что я не контролирую исходный HTML-код страницы; Я контролирую только содержание first.js.

first.js Отправитьсинхронный XHR к файлу PHP и удалил файл PHPsecond.js, Когда readyState достиг 4, у меня было что-то, предупреждающее JS, чтобы остановить поток. Затем я пошел и проверил сервер ... Да,second.js был удален И все же, это не сработает. Я бы закрыл окно предупреждения и код, который былв second.js все равно будет выполнен, несмотря на то, что файл исчез.

Я действительно не знаю, что это значит, но ответ на ваш вопрос, вероятно, «Нет, это невозможно».

 Marcel Korpel21 янв. 2011 г., 16:04
Оба файла JavaScript могут бытьнагруженный одновременно, так что вы, вероятно, удалитеsecond.js после того, как он уже был полностью отправлен в браузер.
 Trevor Burnham21 янв. 2011 г., 17:55
Это забавный метод. Но да, я не удивлен, что это не сработало. И давайте предположим, что нам не разрешено манипулировать сервером, не так ли?

статья описывает способ блокирования загрузки / выполнения скриптов (сторонних) из вашего скрипта (включая теги в заголовке страницы и динамически добавленные теги).

Для обработки существующих тегов на странице:

Используйте MutationObserver для наблюдения за вставкой элементов скрипта, а внутри функции обратного вызова MutationObserver сделайте резервную копию скрипта (чтобы включить / вставить его позже) и измените тип скрипта на «javascript / заблокированный» (не работает в IE, Edge, Firefox). Также вы можете обращаться с устаревшими (но работает)beforescriptexecute событие в Firefox для предотвращения загрузки скрипта.Вручную установите тип "Javascript / заблокирован" (работает везде, включая IE и Edge), как<script type="text/javascript" type="javascript/blocked" src="second.js"></script>затем сделайте резервную копию в обратном вызове MutationObserver и добавьте его позже.

Для обработки динамически добавленных тегов

Обезьяна-патчdocument.createElement.Переопределите дескрипторы «src» и «type» в прототипе HTMLScriptElement.

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

чтобы задержать выполнение некоторого кода

 Trevor Burnham20 янв. 2011 г., 20:48
Правильно, но я спрашиваю: а что, если у меня есть контроль над first.js, а не second.js?

Ваш ответ на вопрос