JavaScript获取当前文件路径

16

如何使用jQuery在javascript中获取当前脚本的路径?

例如,我有一个路径为site.com/js/script.js的脚本,并且在这个脚本中有以下代码:

$(document).ready(function() {
   alert(  ... this code ... );
}

它应该返回一个带有"/js/script.js"消息的警示框。这个函数应该像php中的__FILE__常量一样工作。

那么,我为什么需要这个?

我想动态设置背景图片:

$("somediv").css("background-image", "url(" + $SCRIPT_PATH + "/images/img.png)");

图片目录是/js目录,位于script.js文件附近

js文件夹的名称可以动态设置,因此脚本和图像可以在/myprogect/javascript-files目录中。


1
将您的JavaScript代码文件通过PHP解析器(通常用于“.php”文件)进行处理,然后执行类似于alert('<?= __FILE__ ?>');的操作如何?(我知道这种方法需要避免文件中的杂散的<? ... ?>等内容) - Prusse
只需使用相对路径,例如 $("somediv").css("background-image", "url(./images/img.png)"); - Prusse
我已经尝试过相对路径"./"、"../"和"./../"(用于测试),但它们都不起作用。似乎浏览器会自动将此路径覆盖为"http://site.com/images/img.png"。 - pleerock
可能是重复的问题:如何在脚本内获取脚本文件名? - Bergi
获取脚本路径 - Chaki_Black
显示剩余5条评论
4个回答

27

可以依赖于以下事实:每个 <script> 元素在被插入到 DOM 前都必须先被执行。

这意味着当前被执行的脚本(只要它是作为你的标记的一部分而不是动态插入的)将是使用 getElementsByTagName('script') 检索到的 NodeList 中的最后一个。

这使得你可以读取该元素的 src 属性,并从中确定正在提供该脚本的文件夹,就像这样:

var scriptEls = document.getElementsByTagName( 'script' );
var thisScriptEl = scriptEls[scriptEls.length - 1];
var scriptPath = thisScriptEl.src;
var scriptFolder = scriptPath.substr(0, scriptPath.lastIndexOf( '/' )+1 );

console.log( [scriptPath, scriptFolder] );

我尝试了这种技术,加载了来自不同文件夹的3个脚本,并获得了以下输出

/*
["http://127.0.0.1:8000/dfhdfh/folder1/script1.js", "http://127.0.0.1:8000/dfhdfh/folder1/"]
["http://127.0.0.1:8000/dfhdfh/folder2/script2.js", "http://127.0.0.1:8000/dfhdfh/folder2/"]
["http://127.0.0.1:8000/dfhdfh/folder3/script3.js", "http://127.0.0.1:8000/dfhdfh/folder3/"]
*/

* 来自约翰·雷西格在上面链接的博客

这意味着当脚本最终执行时,它将成为DOM中的最后一个脚本 - 甚至是DOM中的最后一个元素(DOM的其余部分会随着它命中更多的脚本标签而逐步构建,或者直到文档结束)。

更新

正如pimvdb所指出的那样 - 当脚本被评估时,这将起作用。如果您稍后要使用它,则需要以某种方式存储路径。您不能在以后的某个时间查询DOM。如果您对每个脚本使用相同的片段,则每个脚本的scriptFolder的值都将被覆盖。您应该为每个脚本提供一个唯一的变量,也许?

将脚本包装在自己的范围内,可以关闭scriptFolder的值,使其在不害怕被覆盖的情况下可用于脚本的其余部分

(function() {

    var scriptEls = document.getElementsByTagName( 'script' );
    var thisScriptEl = scriptEls[scriptEls.length - 1];
    var scriptPath = thisScriptEl.src;
    var scriptFolder = scriptPath.substr(0, scriptPath.lastIndexOf( '/' )+1 );


    $( function(){
        $('#my-div').click(function(e){
            alert(scriptFolder);
        });
    });


})();

这只有在直接评估时才会给出正确的结果,这是正确的吗?我认为只有在这种情况下,最后一个脚本元素才是执行文件的元素。 - pimvdb
1
是的,我已经考虑过这种方法了。但是...想象一下,如果另一个程序员在文档头部添加了另一个脚本(可能使用了我们脚本的某些函数,或者他不知道不应该添加额外的脚本),那么这将会给另一个程序员带来麻烦。 - pleerock
2
你不能依赖于从脚本标签加载的脚本。 - catbadger

9
请将以下代码添加到您的JS文件中:
var retrieveURL = function(filename) {
    var scripts = document.getElementsByTagName('script');
    if (scripts && scripts.length > 0) {
        for (var i in scripts) {
            if (scripts[i].src && scripts[i].src.match(new RegExp(filename+'\\.js$'))) {
                return scripts[i].src.replace(new RegExp('(.*)'+filename+'\\.js$'), '$1');
            }
        }
    }
};

假设这些是在您的 HTML 中调用的脚本:
<script src="assets/js/awesome.js"></script>
<script src="assets/js/oldcode/fancy-stuff.js"></script>
<script src="assets/js/jquery/cool-plugin.js"></script>

然后,您可以像这样使用该函数。
var awesomeURL = retrieveURL('awesome');
// result : 'assets/js/'

var awesomeURL = retrieveURL('fancy-stuff');
// result : 'assets/js/oldcode/'

var awesomeURL = retrieveURL('cool-plugin');
// result : 'assets/js/jquery/'

请注意,只有当您的HTML中没有两个脚本文件具有相同的名称时,此方法才有效。如果您有两个具有相同名称并位于不同文件夹中的脚本,则结果将不可靠。


注意

如果您动态添加脚本到页面中,请确保在最后一个脚本被添加到DOM后执行您的代码。

以下示例展示了如何处理一个动态加载的脚本,它输出了一个JSON数组,其中包括外部JS文件的src链接和内联脚本的Base64编码字符串:

var addScript = function(src, callback) {
    var s = document.createElement( 'script' );
    s.setAttribute( 'src', src );
    document.body.appendChild( s );
    s.onload = callback;
}

var retrieveURL = function(filename) {
    var scripts = document.getElementsByTagName('script');
    if (scripts && scripts.length > 0) {
        for (var i in scripts) {
            if (scripts[i].src && scripts[i].src.match(new RegExp(filename+'\\.js$'))) {
                return scripts[i].src.replace(new RegExp('(.*)'+filename+'\\.js$'), '$1');
            }
        }
    }
};

addScript('https://code.jquery.com/jquery-1.12.4.min.js', function() {
    var scripts = document.getElementsByTagName('script');
    var sources = [];
    for (var i = 0; i < scripts.length; i++) {
        if(scripts[i].src == '') {
            sources.push(btoa(scripts[i].innerHTML));
        } else {
            sources.push(scripts[i].src);
        }
    }
    document.body.innerHTML += '<pre>' + JSON.stringify(sources,null,2) + '</pre>';
});

另请参见此 Fiddle


如果脚本是动态加载的,那么这个就没用了。 - catbadger
@catbadger:动态加载的脚本仍然会被添加到DOM中,因此这也适用于动态加载的脚本。只需确保在动态加载的脚本已加载后执行该函数即可。请参见我刚刚添加的演示代码,了解如何使用一个动态加载的脚本来实现此操作。 - John Slegers

1

我认为jQuery没有提供这样的功能。 无论如何,您可以通过阅读此处的答案What is my script src URL?获取当前脚本路径(完整的http和相对路径)。


0

你不能在js中设置一种路径变量吗?这样,你就可以将文件路径保存在文件本身中。 例如:

$(function() {
  var FilePath = "js/some/path";
  setMyDynamicImageUsingPath(FilePath);
});

// ...

function setMyDynamicImageUsingPath(path) {
  $("somediv").css("background-image", "url(" + path + "/images/img.png)");
}

很遗憾,我不能这样做。路径名是动态的,所以我无法每次更改固定变量值。 - pleerock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接