JavaScript-如何获得被调用脚本的 URL?

我在文件 http://site1.com/index.html中包含 myscript.js,如下所示:

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

在“ myscript.js”中,我想访问 URL“ http://site2.com/myscript.js”:

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


alert(getScriptURL());

如果从上面提到的 index.html 中调用,它将警告“ http://site2.com/myscript.js”。

83016 次浏览

Can't you use location.href or location.host and then append the script name?

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

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

The variable myScript now has the script dom element. You can get the src url by using myScript.src.

Note that this needs to execute as part of the initial evaluation of the script. If you want to not pollute the Javascript namespace you can do something like:

var getScriptURL = (function() {
var scripts = document.getElementsByTagName('script');
var index = scripts.length - 1;
var myScript = scripts[index];
return function() { return myScript.src; };
})();

You can add id attribute to your script tag (even if it is inside a head tag):

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

and then access to its src as follows:

document.getElementById("myscripttag").src

of course id value should be the same for every document that includes your script, but I don't think it is a big inconvenience for you.

if you have a chance to use jQuery, the code would look like this:

$('script[src$="/myscript.js"]').attr('src');

I wrote a class to find get the path of scripts that works with delayed loading and async script tags.

I had some template files that were relative to my scripts so instead of hard coding them I made created the class to do create the paths automatically. The full source is here on github.

A while ago I had use arguments.callee to try and do something similar but I recently read on the MDN that it is not allowed in strict mode.

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('.');
};
}

Following code lets you find the script element with given name

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;
}
}

Everything except IE supports

document.currentScript

Simple and straightforward solution that work very well :

If it not IE you can use document.currentScript
For IE you can do document.querySelector('script[src*="myscript.js"]')
so :

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

In a module script, you can use:

 import.meta.url

as describe in mdn

document.currentScript.src

will return the URL of the current Script URL.

Note: If you have loaded the script with type Module then use

import.meta.url

for more import.meta & currentScript.src

Some necromancy, but here's a function that tries a few methods

function getScriptPath (hint) {
if (  typeof document === "object" &&
typeof document.currentScript === 'object' &&
document.currentScript && // null detect
typeof document.currentScript.src==='string' &&
document.currentScript.src.length > 0) {
return document.currentScript.src;
}
    

    

let here = new Error();
if (!here.stack) {
try { throw here;} catch (e) {here=e;}
}
if (here.stack) {
        

const stacklines = here.stack.split('\n');
console.log("parsing:",stacklines);
let result,ok=false;
stacklines.some(function(line){
if (ok) {
const httpSplit=line.split(':/');
const linetext = httpSplit.length===1?line.split(':')[0]:httpSplit[0]+':/'+( httpSplit.slice(1).join(':/').split(':')[0]);
const chop = linetext.split('at ');
if (chop.length>1) {
result = chop[1];
if ( result[0]!=='<') {
console.log("selected script from stack line:",line);
return true;
}
result=undefined;
}
return false;
}
ok = line.indexOf("getScriptPath")>0;
return false;
});
return result;
}
    

if ( hint && typeof document === "object") {
const script = document.querySelector('script[src="'+hint+'"]');
return script && script.src && script.src.length && script.src;
}
    

}
   

console.log("this script is at:",getScriptPath ())