JavaScript - как мне получить URL-адрес вызываемого скрипта?

81

Я включаю myscript.js в файл http://site1.com/index.htmlследующим образом:

<script src=http://site2.com/myscript.js></script>

Внутри myscript.js я хочу получить доступ к URL-адресу http://site2.com/myscript.js . Хотелось бы иметь что-то вроде этого:

function getScriptURL() {
    // something here
    return s
}

alert(getScriptURL());

Что будет предупреждать " http://site2.com/myscript.js ", если вызывается из index.html, упомянутого выше.

MikeC8
источник
возможный дубликат URL-адреса моего скрипта src?
ripper234
Основываясь на ваших примерах URL-адресов, вы можете захотеть отметить, какое поведение вы ожидаете, если браузер настроен на блокировку сторонних скриптов.

Ответы:

58

Из http://feather.elektrum.org/book/src.html :

var scripts = document.getElementsByTagName('script');
var index = scripts.length - 1;
var myScript = scripts[index];

Теперь у переменной myScriptесть элемент dom скрипта. Вы можете получить URL-адрес src, используя myScript.src.

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

var getScriptURL = (function() {
    var scripts = document.getElementsByTagName('script');
    var index = scripts.length - 1;
    var myScript = scripts[index];
    return function() { return myScript.src; };
})();
ламбак
источник
23
Всегда ли это будет возвращать URL-адрес правильного сценария во всех браузерах? Похоже, он вернет последний тег скрипта, но что, если в документе есть более одного тега скрипта?
MikeC8 04
3
Хорошо ... тогда у меня возникает вопрос: все ли браузеры всегда полностью загружают и выполняют все содержимое удаленного скрипта перед переходом к следующему тегу скрипта? Насколько строго это стандартизировано? Я мог представить, что это происходит параллельно ...
MikeC8
1
Требуется, чтобы сценарии выполнялись полностью и по порядку, поскольку в этом случае тег сценария содержит файл document.write. Это причина для рекомендаций размещать скрипты внизу страницы, потому что они фактически блокируют загрузку другого контента. Тем не менее, HTML5 изменяет это с помощью атрибутов async и defer
lambacck
9
Это не сработает, если вы загрузите скрипт после загрузки страницы, используя что-то вроде этого: document.getElementsByTagName("head")[0].appendChild(scriptElement);
Seanonymous
16
Я сталкивался со случаем, когда этот алгоритм не работает надежно. Другие теги сценария, для которых установлено значение async, могут выполняться между запросом и запуском вашего сценария. Эти скрипты могут добавлять в DOM другие скрипты, которые появляются после вашего. Когда ваш скрипт запускает последний скрипт на странице, он больше не ваш, и srcвозвращается ошибка .
Карл
54

Вы можете добавить атрибут id в свой тег скрипта (даже если он находится внутри тега head):

<script id="myscripttag" src="http://site2.com/myscript.js"></script>

а затем доступ к его src следующим образом:

document.getElementById("myscripttag").src

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

tsds
источник
1
Этот ответ должен быть отмечен как «принятый», поскольку он охватывает случаи, когда вы вызываете метод не в «глобальном» контексте сценария или в «асинхронном» сценарии, и он не зависит от реализации браузера.
Сергей Коваленко
Обратите внимание, что .srcможет возвращать абсолютный путь, даже если был указан относительный путь. Можно использовать.getAttribute('src')
Илья Зеленько
18

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

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

Некоторое время назад я использовал arguments.callee, чтобы попытаться сделать что-то подобное, но недавно я прочитал в MDN, что это запрещено в строгом режиме .

function ScriptPath() {
  var scriptPath = '';
  try {
    //Throw an error to generate a stack trace
    throw new Error();
  }
  catch(e) {
    //Split the stack trace into each line
    var stackLines = e.stack.split('\n');
    var callerIndex = 0;
    //Now walk though each line until we find a path reference
    for(var i in stackLines){
      if(!stackLines[i].match(/http[s]?:\/\//)) continue;
      //We skipped all the lines with out an http so we now have a script reference
      //This one is the class constructor, the next is the getScriptPath() call
      //The one after that is the user code requesting the path info (so offset by 2)
      callerIndex = Number(i) + 2;
      break;
    }
    //Now parse the string for each section we want to return
    pathParts = stackLines[callerIndex].match(/((http[s]?:\/\/.+\/)([^\/]+\.js)):/);
  }

  this.fullPath = function() {
    return pathParts[1];
  };

  this.path = function() {
    return pathParts[2];
  };

  this.file = function() {
    return pathParts[3];
  };

  this.fileNoExt = function() {
    var parts = this.file().split('.');
    parts.length = parts.length != 1 ? parts.length - 1 : 1;
    return parts.join('.');
  };
}
QueueHammer
источник
1
Немного поздно для вечеринки, но я пробовал этот фрагмент кода и обнаружил, что часть, где он добавляет 2 к текущему индексу в цикле for, «callerIndex = Number (i) + 2;» кажется, что ломается ненужно и не работает. Просто убрав "+ 2", он заработает. Есть ли что-то, что я неправильно истолковываю, или какой-то другой сценарий, для которого может понадобиться +2?
Скотт Смит
2
вам не нужно бросать "Error" таким образом (чтобы получить ".stack"), это просто объект, подобный другим: console.log (new Error (). stack);
Абдулла
1
Спасибо за эту идею и спасибо @ AbdullahAydın за идею предотвращения броска. Тогда я полагаю, что следующий однострочный текст поможет, не так ли? var scriptUrl = new Error (). stack.match (/ @ (https?: \ / \ /.+): \ d +: \ d + /) [1]
Пьер-Антуан
1
Также @ Pierre-Antoine имейте в виду, что свойство Error.prototype.stack нестандартно: / вы должны использовать его с осторожностью. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Абдулла,
3
@ AbdullahAydın: Обратите внимание, что свойство stack для новой ошибки не заполняется в браузерах IE и Edge до тех пор, пока ошибка не будет выдана.
Боб Арлоф, 03
15

если у вас есть возможность использовать jQuery, код будет выглядеть так:

$('script[src$="/myscript.js"]').attr('src');
Мистер Тыква
источник
Работает ли он со сценариями отложенной, асинхронной и отложенной загрузки?
Стефан
Он просто ищет в DOM тег скрипта с src "/myscript.js". другие атрибуты не имеют значения
Ребс
Чтобы использовать это с wordpress в любом другом месте, куда добавляется версия, вы должны использовать $ ('script [src * = "/ myscript.js"]'). Attr ('src'); таким образом он проигнорирует? ver = 2.3.3 в конце скрипта. * Будет продолжать работать независимо от того, что находится в конце.
Mav2287 02
15

Простое и понятное решение, которое очень хорошо работает:

Если это не IE, вы можете использовать его. document.currentScript
Для IE вы можете сделать document.querySelector('script[src*="myscript.js"]')
это:

function getScriptURL(){
 var script =  document.currentScript || document.querySelector('script[src*="myscript.js"]')
 return script.src
}
Pery Mimon
источник
2

Следующий код позволяет вам найти элемент скрипта с заданным именем

var scripts = document.getElementsByTagName( 'script' );
        var len = scripts.length
        for(var i =0; i < len; i++) {
            if(scripts[i].src.search("<your JS file name") > 0 && scripts[i].src.lastIndexOf("/") >= 0) {
                absoluteAddr = scripts[i].src.substring(0, scripts[i].src.lastIndexOf("/") + 1);
                break;
            }
        }
Варун Бхатия
источник
-6

Разве вы не можете использовать location.href или location.host, а затем добавить имя скрипта?

Павел
источник
1
Это не сработает, потому что скрипт выполняется на странице site1.com/index.html . Таким образом, даже если скрипт загружается с site2.com, если вы обращаетесь к местоположению из скрипта, он вернет « site1.com/index.html » ...
MikeC8 04