Как вставить элемент сразу после встроенного тега скрипта в javascript? [Дубликат]

Имейте в виду, что независимо от сценария причина всегда одинакова в .NET:

Вы пытаетесь использовать ссылочную переменную, значение которой Nothing / null. Если для ссылочной переменной значение Nothing / null, это означает, что на самом деле оно не содержит ссылку на экземпляр любого объекта, который существует в куче.

Вы либо никогда не присваивали какую-либо переменную, никогда не создавали экземпляр значения, присвоенного переменной, или вы вручную устанавливали переменную, равную Nothing / null, или вы вызывали функцию, которая установите для этой переменной значение Nothing / null.

231
задан Shog9 2 April 2009 в 19:24
поделиться

12 ответов

Вот немного polyfill, который использует document.CurrentScript, если он существует, и возвращается к поиску скрипта по идентификатору.

<script id="uniqueScriptId">
    (function () {
        var thisScript = document.CurrentScript || document.getElementByID('uniqueScriptId');

        // your code referencing thisScript here
    ());
</script>

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

Не проиндексирован, поэтому оставляйте отзыв для других, если вы пытаетесь это сделать.

501
ответ дан brice 28 August 2018 в 00:51
поделиться
  • 1
    Вау! Потоки currentScript! – m93a 25 October 2013 в 14:38
  • 2
    Это должен быть ответ. – Royi Namir 15 May 2014 в 13:52
  • 3
    Согласитесь с @RoyiNamir. Это лучший ответ. – Hans 23 May 2014 в 19:09
  • 4
    Спасибо, ребята, но вы знаете, что я ответил 4 years после принятого ответа, правильно :) – brice 25 May 2014 в 01:26
  • 5
    Вариант 1 не работает для меня в Waterfox 28 (возвращает null). – Josh 27 June 2014 в 21:57
  • 6
    & Quot; document.currentScript & Quot; не работает для меня с динамически загружаемыми скриптами, возвращает null в последнем хромовом / firefox, последнем выполненном скрипте, работает нормально – xwild 12 February 2016 в 05:15
  • 7
    Атрибут id является недопустимым в элементе script. Какие проблемы могут возникнуть при таком подходе? – n.r. 19 January 2018 в 18:14

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

var scripts = document.getElementsByTagName( 'script' );
var thisScriptTag = scripts[ scripts.length - 1 ];
85
ответ дан Coffee Bite 28 August 2018 в 00:51
поделиться
  • 1
    Это просто и элегантно. Вот пример этого в новом API Google Карт / Визуализации, если вы распакуете javascript. Они загружают данные JSON из тега сценария, см. ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js – Jason Thrasher 18 November 2010 в 00:13
  • 2
    Это отличная идея, и она обычно работает для меня. Но я должен добавить, что бывают случаи, когда я обнаружил, что он возвращает ссылку на другой скрипт. Не знаете, почему - не смогли отследить это. Следовательно, я обычно использую другой метод, например, я жестко программирую имя файла сценария и ищу тег сценария с этим именем файла. – Ken Smith 19 November 2011 в 00:28
  • 3
    Один из примеров, когда я могу думать о том, где это может возвращать неверные результаты, - это то, что тег скрипта добавляется в DOM асинхронно. – Coffee Bite 25 November 2011 в 16:41
  • 4
    Да, это может иметь непредсказуемые результаты, чтобы вы могли вместо этого использовать селектор: $ ('script [src * = & quot; /mysource.js"]') ??? – Jason Sebring 27 November 2012 в 23:52
  • 5
    Это не работает, когда вы загружаете скрипты после загрузки страницы. Вероятно, вы не получите правильный тег. – ThemeZ 22 February 2013 в 08:32

Сценарий выполняется последовательно, только если у них нет атрибута «отложить» или «асинхронный». Знание одного из возможных атрибутов ID / SRC / TITLE тега скрипта также может работать в этих случаях. Итак, оба предложения Грега и Джастина верны.

В списке WHATWG уже есть предложение для document.currentScript.

EDIT: Firefox> 4 уже реализует это очень полезное свойство, но он недоступен в IE11, который последний раз я проверял и доступен только в Chrome 29 и Safari 8.

EDIT: Никто не упомянул коллекцию document.scripts, но я считаю, что следующая альтернатива может быть хорошей альтернативой перекрестного браузера для запуска текущего скрипта:

var me = document.scripts[document.scripts.length -1];
9
ответ дан ExceptionLimeCat 28 August 2018 в 00:51
поделиться

Следуйте этим простым шагам, чтобы получить ссылку на текущий исполняемый блок сценариев:

  1. Поместите некоторую случайную уникальную строку в блок сценария (должны быть уникальными / разными в каждом блоке скрипта)
  2. Итерировать результат document.getElementsByTagName ('script'), просматривая уникальную строку из каждого своего содержимого (полученное из свойства innerText / textContent).

Пример (ABCDE345678 является уникальным ID) :

<script type="text/javascript">
var A=document.getElementsByTagName('script'),i=count(A),thi$;
for(;i;thi$=A[--i])
  if((thi$.innerText||thi$.textContent).indexOf('ABCDE345678'))break;
// Now thi$ is refer to current script block
</script>

btw, для вашего случая вы можете просто использовать старомодный метод document.write () для включения другого скрипта. Поскольку вы упомянули, что DOM пока не отображается, вы можете воспользоваться тем фактом, что браузер всегда выполняет скрипт в линейной последовательности (за исключением отложенного, который будет отображаться позже), поэтому остальная часть вашего документа по-прежнему «не существует». Все, что вы пишете через document.write (), будет размещено сразу после сценария вызывающего абонента.

Пример исходной HTML-страницы :

<!doctype html>
<html><head>
<script src="script.js"></script>
<script src="otherscript.js"></script>
<body>anything</body></html>

Содержание script.js :

document.write('<script src="inserted.js"></script>');

После визуализации структура DOM станет:

HEAD
  SCRIPT script.js
  SCRIPT inserted.js
  SCRIPT otherscript.js
BODY
2
ответ дан Ferdinand Liu 28 August 2018 в 00:51
поделиться
  • 1
    Кажется, что это работает только для встроенных скриптов, а не для внешних скриптов. В последнем случае все свойства innerText, text и textContent пусты. – Jos de Jong 6 May 2014 в 09:55

Вероятно, проще всего было бы дать вашему тегу скрипта атрибут id.

12
ответ дан Greg 28 August 2018 в 00:51
поделиться
  • 1
    Хотя вы правы, есть много случаев, когда вопрос OP действителен, пара будет: 1) когда вы сканируете 2), когда вы работаете с DOM клиента, и он не хочет менять – nichochar 8 September 2015 в 23:42

Он должен работать при загрузке страницы и при добавлении тега скрипта с помощью javascript (например, с ajax)

<script id="currentScript">
var $this = document.getElementById("currentScript");
$this.setAttribute("id","");
//...
</script>
6
ответ дан HoLyVieR 28 August 2018 в 00:51
поделиться
  • 1
    единственный вариант, который работал на меня, большое спасибо! – FLCL 3 May 2015 в 19:43

Если вы можете считать имя файла сценария, вы можете его найти. До сих пор я только что протестировал следующую функцию в Firefox.

  function findMe(tag, attr, file) {
    var tags = document.getElementsByTagName(tag);
    var r = new RegExp(file + '$');
    for (var i = 0;i < tags.length;i++) {
      if (r.exec(tags[i][attr])) {
        return tags[i][attr];
      }
    }
  };
  var element = findMe('script', 'src', 'scripts.js');
1
ответ дан Justin Love 28 August 2018 в 00:51
поделиться

Рассмотрим этот алгоритм. Когда ваш скрипт загружается (если есть несколько идентичных скриптов), просмотрите document.scripts, найдите первый скрипт с правильным атрибутом «src» и сохраните его и пометьте как «посещенный» атрибутом данных или уникальным именем класса.

Когда следующий скрипт загружается, снова сканируйте документы document.scripts, передавая любой скрипт, уже отмеченный как посещенный. Возьмите первый невидимый экземпляр этого скрипта.

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

(function () {
  var scripts = document.scripts;

  // Scan for this data-* attribute
  var dataAttr = 'data-your-attribute-here';

  var i = 0;
  var script;
  while (i < scripts.length) {
    script = scripts[i];
    if (/your_script_here\.js/i.test(script.src)
        && !script.hasAttribute(dataAttr)) {

        // A good match will break the loop before
        // script is set to null.
        break;
    }

    // If we exit the loop through a while condition failure,
    // a check for null will reveal there are no matches.
    script = null;
    ++i;
  }

  /**
   * This specific your_script_here.js script tag.
   * @type {Element|Node}
   */
  var yourScriptVariable = null;

  // Mark the script an pass it on.
  if (script) {
    script.setAttribute(dataAttr, '');
    yourScriptVariable = script;
  }
})();

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

Затем отметьте этот узел, если он найден, с атрибутом данных поэтому последующие сканирования не будут выбирать его. Это похоже на алгоритмы BFS и DFS с обходным трафиком, где узлы могут быть помечены как «посещенные», чтобы предотвратить повторный просмотр.

2
ответ дан LSOJ 28 August 2018 в 00:51
поделиться
  • 1
    Добро пожаловать в Stack Overflow. Не хотите ли вы включить код с алгоритмом? – Gary99 12 June 2017 в 19:05
  • 2
    Тар вы идете, @ Gary99 – LSOJ 13 June 2017 в 21:27

Подход для решения проблемы с асинхронным и отложенные сценарии - использовать обработчик onload - установить обработчик onload для всех тегов скриптов, а первый из них должен быть вашим.

function getCurrentScript(callback) {
  if (document.currentScript) {
    callback(document.currentScript);
    return;
  }
  var scripts = document.scripts;
  function onLoad() {
    for (var i = 0; i < scripts.length; ++i) {
      scripts[i].removeEventListener('load', onLoad, false);
    }
    callback(event.target);
  }
  for (var i = 0; i < scripts.length; ++i) {
    scripts[i].addEventListener('load', onLoad, false);
  }
}

getCurrentScript(function(currentScript) {
  window.console.log(currentScript.src);
});
3
ответ дан Pete Blois 28 August 2018 в 00:51
поделиться

Чтобы получить скрипт, загруженный в настоящий момент скриптом, вы можете использовать

var thisScript = document.currentScript;

. Вам нужно сохранить ссылку в начале вашего скрипта, чтобы вы могли позвонить позже

var url = thisScript.src
1
ответ дан Peter Lakatos - appnomads 28 August 2018 в 00:51
поделиться

Я нашел следующий код наиболее согласованным, показательным и простым.

var scripts = document.getElementsByTagName('script');
var thisScript = null;
var i = scripts.length;
while (i--) {
  if (scripts[i].src && (scripts[i].src.indexOf('yourscript.js') !== -1)) {
    thisScript = scripts[i];
    break;
  }
}
console.log(thisScript);
0
ответ дан Travis Tidwell 28 August 2018 в 00:51
поделиться

У меня есть это, которое работает в FF3, IE6 & amp; 7. Методы в загружаемых сценариях по запросу недоступны до тех пор, пока загрузка страницы не будет завершена, но это все еще очень полезно.

//handle on-demand loading of javascripts
makescript = function(url){
    var v = document.createElement('script');
    v.src=url;
    v.type='text/javascript';

    //insertAfter. Get last <script> tag in DOM
    d=document.getElementsByTagName('script')[(document.getElementsByTagName('script').length-1)];
    d.parentNode.insertBefore( v, d.nextSibling );
}
-1
ответ дан user 28 August 2018 в 00:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: