JavaScript - Wie erhalte ich die URL des aufgerufenen Skripts?

79

Ich füge myscript.js http://site1.com/index.htmlwie folgt in die Datei ein :

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

In "myscript.js" möchte ich Zugriff auf die URL " http://site2.com/myscript.js " erhalten. Ich hätte gerne so etwas:

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

alert(getScriptURL());

Was " http://site2.com/myscript.js " alarmieren würde, wenn es von der oben erwähnten index.html aufgerufen würde .

MikeC8
quelle
Mögliches Duplikat von Was ist meine Skript-src-URL?
Ripper234
Anhand Ihrer Beispiel-URLs möchten Sie möglicherweise feststellen, welches Verhalten Sie erwarten, wenn der Browser Skripte von Drittanbietern blockiert.

Antworten:

57

Von http://feather.elektrum.org/book/src.html :

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

Die Variable hat myScriptjetzt das Skript dom-Element. Sie können die src-URL mithilfe von abrufen myScript.src.

Beachten Sie, dass dies im Rahmen der anfänglichen Evaluierung des Skripts ausgeführt werden muss. Wenn Sie den Javascript-Namespace nicht verschmutzen möchten, können Sie Folgendes tun:

var getScriptURL = (function() {
    var scripts = document.getElementsByTagName('script');
    var index = scripts.length - 1;
    var myScript = scripts[index];
    return function() { return myScript.src; };
})();
Lambacck
quelle
23
Gibt dies in allen Browsern immer die URL des richtigen Skripts zurück? Dies sieht so aus, als würde das letzte Skript-Tag zurückgegeben. Was ist jedoch, wenn das Dokument mehr als ein Skript-Tag enthält?
MikeC8
3
Ok ... meine Frage lautet dann: Laden alle Browser immer vollständig und führen den gesamten Inhalt eines Remote-Skripts aus, bevor Sie mit dem nächsten Skript-Tag fortfahren? Wie streng ist dies standardisiert? Ich könnte mir vorstellen, dass es parallel passiert ...
MikeC8
1
Es ist erforderlich, dass Skripte vollständig und in der richtigen Reihenfolge ausgeführt werden, da das Skript-Tag ein document.write enthalten würde. Dies ist der Grund für die Empfehlungen, Skripte am Ende der Seite einzufügen, da sie das Laden anderer Inhalte blockieren. HTML5 ändert dies jedoch mithilfe der Attribute async und defer
lambacck
9
Dies funktioniert nicht, wenn Sie das Skript laden, nachdem die Seite wie document.getElementsByTagName("head")[0].appendChild(scriptElement);
folgt
16
Ich bin auf einen Fall gestoßen, in dem dieser Algorithmus nicht zuverlässig funktioniert. Andere Skript-Tags, die auf asynchron eingestellt sind, können zwischen dem angeforderten Skript und der Ausführung ausgeführt werden. Diese Skripte können dem DOM weitere Skripte hinzufügen, die nach Ihrem angezeigt werden. Wenn Ihr Skript ausgeführt wird, gehört das letzte Skript auf der Seite nicht mehr Ihnen und das falsche srcwird zurückgegeben.
Karl
53

Sie können Ihrem Skript-Tag ein ID-Attribut hinzufügen (auch wenn es sich in einem Head-Tag befindet):

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

und dann Zugriff auf seine src wie folgt:

document.getElementById("myscripttag").src

Natürlich sollte der ID-Wert für jedes Dokument, das Ihr Skript enthält, gleich sein, aber ich denke nicht, dass dies eine große Unannehmlichkeit für Sie ist.

tsds
quelle
1
Diese Antwort sollte als "akzeptiert" markiert werden, da sie die Fälle abdeckt, in denen Sie die Methode nicht im "globalen" Skriptkontext oder im "asynchronen" Skript aufrufen, und sie hängt nicht von der Browserimplementierung ab.
Sergei Kovalenko
Beachten Sie, dass .srcein absoluter Pfad zurückgegeben werden kann, selbst wenn ein relativer Pfad angegeben wurde. Sie können verwenden.getAttribute('src')
Илья Зеленько
18

Ich habe eine Klasse geschrieben, um den Pfad von Skripten zu finden, die mit verzögertem Laden und asynchronen Skript-Tags funktionieren.

Ich hatte einige Vorlagendateien, die relativ zu meinen Skripten waren. Anstatt sie hart zu codieren, habe ich die Klasse erstellt, um die Pfade automatisch zu erstellen. Die vollständige Quelle finden Sie hier auf Github.

Vor einiger Zeit hatte ich argument.callee verwendet, um etwas Ähnliches zu versuchen, aber ich habe kürzlich im MDN gelesen, dass es im strengen Modus nicht erlaubt ist .

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
quelle
1
Ein bisschen spät zur Party hier, aber ich habe dieses Code-Snippet ausprobiert und festgestellt, dass der Teil, in dem es 2 zum aktuellen Index in der for-Schleife hinzufügt, "callerIndex = Number (i) + 2;" scheint zu brechen unnötig und führt dazu, dass es nicht funktioniert. Durch einfaches Eliminieren der "+ 2" funktioniert es. Gibt es etwas, das ich falsch interpretiere, oder ein anderes Szenario, für das diese + 2 notwendig wäre?
Scott Smith
2
Sie müssen "Error" nicht auf diese Weise auslösen (um ".stack" zu erhalten). Es ist nur ein Objekt wie andere: console.log (new Error (). stack);
Abdullah
1
Danke für diese Idee und danke an @ AbdullahAydın für die Idee, einen Wurf zu verhindern. Dann würde wohl der folgende Einzeiler den Trick machen, nicht wahr? var scriptUrl = neuer Fehler (). stack.match (/ @ (https ?: \ / \ /.+): \ d +: \ d + /) [1]
Pierre-Antoine
1
Beachten Sie auch bei @ Pierre-Antoine, dass die Eigenschaft Error.prototype.stack nicht dem Standard entspricht: / Sie sollten sie mit Vorsicht verwenden. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Abdullah
3
@ AbdullahAydın: Beachten Sie, dass die Stack-Eigenschaft eines neuen Fehlers erst im IE- und Edge-Browser ausgefüllt wird, wenn der Fehler ausgelöst wird.
Bob Arlof
15

Wenn Sie die Möglichkeit haben, jQuery zu verwenden, sieht der Code folgendermaßen aus:

$('script[src$="/myscript.js"]').attr('src');
Mr. Pumpkin
quelle
Funktioniert es mit verzögerten, asynchronen und verzögerten Ladeskripten?
Stephan
Es wird nur im DOM nach einem Skript-Tag mit dem src "/myscript.js" gesucht. andere Attribute spielen keine Rolle
Rebs
Um dies mit WordPress an einer anderen Stelle zu verwenden, an der die Version angehängt wird, sollten Sie $ ('script [src * = "/ myscript.js"]') verwenden. Attr ('src'); Auf diese Weise wird? ver = 2.3.3 am Ende des Skripts ignoriert. Das * sorgt dafür, dass es funktioniert, unabhängig davon, was am Ende steht.
Mav2287
14

Einfache und unkomplizierte Lösung, die sehr gut funktioniert:

Wenn es nicht IE ist, können Sie document.currentScript
Für IE können Sie dies tun document.querySelector('script[src*="myscript.js"]')
:

function getScriptURL(){
 var script =  document.currentScript || document.querySelector('script[src*="myscript.js"]')
 return script.src
}
pery mimon
quelle
2

Mit dem folgenden Code können Sie das Skriptelement mit dem angegebenen Namen finden

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;
            }
        }
Varun Bhatia
quelle
-6

Können Sie nicht location.href oder location.host verwenden und dann den Skriptnamen anhängen?

Paul
quelle
1
Das funktioniert nicht, da das Skript auf der Seite site1.com/index.html ausgeführt wird. Selbst wenn das Skript von site2.com geladen wird, wird beim Zugriff auf den Speicherort innerhalb des Skripts " site1.com/index.html " zurückgegeben ...
MikeC8