如何获得指定为 < script > 标记的‘ src’的文件内容?

如果我有这样的脚本标签:

<script
id = "myscript"
src = "http://www.example.com/script.js"
type = "text/javascript">
</script>

我想获取“ script.js”文件的内容。我在考虑类似 document.getElementById("myscript").text的东西,但它在这种情况下不起作用。

58661 次浏览

要获取文件 http://www.example.com/script.js的内容吗?如果是这样,您可以转向 AJAX 方法来获取它的内容,假设它与页面本身位于同一个服务器上。

不知道你为什么要这么做?

另一种方法是将脚本保存在某个隐藏元素中,并使用 Eval 运行它。然后可以查询对象 innerHtml 属性。

如果需要 src 属性的内容,则必须执行 ajax 请求并查看 response setext。如果你在哪里有 js,你可以通过 innerHTML 访问它。

这可能会引起人们的兴趣: http://ejohn.org/blog/degrading-script-tags/

如果您希望访问 <script>标记的属性,而不是 script.js 的内容,那么 XPath可能就是您想要的。

它将允许您获取每个脚本属性。

如果您需要的是 example.js 文件内容,那么您可以发出一个 AJAX 请求来获取它。

如果提供了 src 属性,则用户代理是 需要忽略元素的内容,如果需要从外部脚本访问该属性,则可能出现了错误。

更新: 我看到您已经添加了一个注释,大意是您想要缓存脚本并在以后使用它。为了什么?假设您的 HTTP 对缓存友好,那么浏览器可能已经满足了您的缓存需求。

.Text 确实给出了标记的内容,只是在打开的标记和结束标记之间没有任何内容。可以使用以下方法获取元素的 src 属性。然后,如果你想得到 javascript 文件,你可以点击链接并为它发出 ajax 请求。

我认为内容不会通过 DOM 提供。您可以获取 src 属性的值并使用 AJAX 从服务器请求文件。

在对我之前的回答的评论中:

我希望存储脚本的内容,这样我就可以缓存它,并在一段时间后直接使用它,而不必从外部 Web 服务器(不是在页面的同一台服务器上)获取它

在这种情况下,最好使用服务器端脚本来获取和缓存脚本文件。根据您的服务器设置,您可以只是 wget 文件(如果您希望它发生变化,可以定期通过 cron)或者使用您选择的语言的小脚本执行类似的操作。

使用2008年风格的 DOM 绑定更好:

document.getElementById('myscript').getAttribute("src");
document.getElementById('myscript').getAttribute("type");

您希望使用 innerHTML 属性获取 script 标记的内容:

document.getElementById("myscript").innerHTML

但正如@olle 在另一个回答中所说,你可能想读一读: Http://ejohn.org/blog/degrading-script-tags/

我建议这个问题的答案是使用 DOM 元素的“ innerHTML”属性。当然,如果是 脚本已经加载,那么就需要通过一个 Ajax 调用来获得 没有

因此,苏根德兰应该是正确的(不知道为什么他没有解释就被否决了)。

var scriptContent = document.getElementById("myscript").innerHTML;

Script 元素的 innerHTML 属性应该以字符串的形式提供 script 内容,只要 script 元素是:

  • 一个内联的脚本,或者
  • (如果使用 src 属性)

Olle 也给出了答案,但我认为他建议需要首先通过 ajax 加载,这让问题变得“混乱”了,我认为他的意思是“内联”而不是介于两者之间。

如果你在哪里有 js 之间,你可以通过 innerHTML 访问它。


关于这个技术的有用性:

在获得了不包含在我自己的脚本中的“未定义变量”(例如从工具栏或扩展插入的错误脚本)之后,我试图将这种技术用于客户端错误日志记录(javascript 异常)——所以我不认为这是一种解决方法。

更新: HTML 导入现在是 不赞成(选择)。

---

我知道这有点晚了,但有些浏览器支持标记 LINK rel="import"属性。

Http://www.html5rocks.com/en/tutorials/webcomponents/imports/

<link rel="import" href="/path/to/imports/stuff.html">

对于其他人来说,Ajax 仍然是首选的方式。

是的,阿贾克斯是做到这一点的方式,因为在公认的答案。如果你仔细研究细节,会发现很多陷阱。如果您使用的是 jQuery.load(...),那么假定的内容类型是错误的(html 而不是 application/javascript) ,这可能会因为在您的(scriptNode)中放入不需要的 <br>而造成混乱。InnerText 之类的。然后,如果您使用 jQuery.getScript(...),下载的脚本会立即执行,这可能不是您想要的(可能会打乱您想要加载文件的顺序,以防您有几个这样的文件)

我发现最好使用 jQuery.ajaxdataType: "text"

我在一个带有框架集的项目中使用了这种 Ajax 技术,其中框架集和/或多个框架需要相同的 JavaScript,以避免让服务器多次发送该 JavaScript。

下面是经过测试和工作的代码:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<script id="scriptData">
var scriptData = [
{ name: "foo"    , url: "path/to/foo"    },
{ name: "bar"    , url: "path/to/bar"    }
];
</script>
<script id="scriptLoader">
var LOADER = {
loadedCount: 0,
toBeLoadedCount: 0,
load_jQuery: function (){
var jqNode = document.createElement("script");
jqNode.setAttribute("src", "/path/to/jquery");
jqNode.setAttribute("onload", "LOADER.loadScripts();");
jqNode.setAttribute("id", "jquery");
document.head.appendChild(jqNode);
},
loadScripts: function (){
var scriptDataLookup = this.scriptDataLookup = {};
var scriptNodes = this.scriptNodes = {};
var scriptNodesArr = this.scriptNodesArr = [];
for (var j=0; j<scriptData.length; j++){
var theEntry = scriptData[j];
scriptDataLookup[theEntry.name] = theEntry;
}
//console.log(JSON.stringify(scriptDataLookup, null, 4));
for (var i=0; i<scriptData.length; i++){
var entry = scriptData[i];
var name = entry.name;
var theURL = entry.url;
this.toBeLoadedCount++;
var node = document.createElement("script");
node.setAttribute("id", name);
scriptNodes[name] = node;
scriptNodesArr.push(node);
jQuery.ajax({
method   : "GET",
url      : theURL,
dataType : "text"
}).done(this.makeHandler(name, node)).fail(this.makeFailHandler(name, node));
}
},
makeFailHandler: function(name, node){
var THIS = this;
return function(xhr, errorName, errorMessage){
console.log(name, "FAIL");
console.log(xhr);
console.log(errorName);
console.log(errorMessage);
debugger;
}
},
makeHandler: function(name, node){
var THIS = this;
return function (fileContents, status, xhr){
THIS.loadedCount++;
//console.log("loaded", name, "content length", fileContents.length, "status", status);
//console.log("loaded:", THIS.loadedCount, "/", THIS.toBeLoadedCount);
THIS.scriptDataLookup[name].fileContents = fileContents;
if (THIS.loadedCount >= THIS.toBeLoadedCount){
THIS.allScriptsLoaded();
}
}
},
allScriptsLoaded: function(){
for (var i=0; i<this.scriptNodesArr.length; i++){
var scriptNode = this.scriptNodesArr[i];
var name = scriptNode.id;
var data = this.scriptDataLookup[name];
var fileContents = data.fileContents;
var textNode = document.createTextNode(fileContents);
scriptNode.appendChild(textNode);
document.head.appendChild(scriptNode); // execution is here
//console.log(scriptNode);
}
// call code to make the frames here
}
};
</script>
</head>
<frameset rows="200pixels,*" onload="LOADER.load_jQuery();">
<frame src="about:blank"></frame>
<frame src="about:blank"></frame>
</frameset>
</html>

相关问题

Dr 脚本标记不受 CORS原产地相同政策的约束,因此 javascript/DOM 不能提供对通过 <script>标记加载的资源的文本内容的访问,否则它将中断 same-origin-policy

长版本: 大多数其他的回答(和接受的答案)正确地指出,“ 正确”方式获得通过 <script>加载到页面中的 javascript 文件的文本内容,是使用 XMLHttpRequest对脚本 src属性中指示的资源执行另一个单独的额外请求,下面简短的 javascript 代码将演示这一点。然而,我发现其他的答案并没有解决为什么要获取 javascript 文件的文本内容的问题,即允许访问通过 <script src=[url]></script>包含的文件的内容会违反 CORS的策略,例如,现代浏览器阻止资源的 XHR 不提供 访问-控制-允许-起源头,因此浏览器不允许任何其他方式,除了那些受到 CORS的影响,以获取内容。

使用以下代码(如其他问题“使用 XHR/AJAX”中提到的) ,可以对文档中所有非内联脚本标记执行另一个请求。

function printScriptTextContent(script)
{
var xhr = new XMLHttpRequest();
xhr.open("GET",script.src)
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log("the script text content is",xhr.responseText);
}
};
xhr.send();
}
Array.prototype.slice.call(document.querySelectorAll("script[src]")).forEach(printScriptTextContent);

因此,我不会重复这一点,相反,我想通过这个答案来补充一下为什么会这样

这很有趣,但我们不能,我们必须通过互联网再次获取它们。

浏览器很可能会读取他的缓存,但仍然会发送一个 ping 来验证内容长度。

[...document.scripts].forEach((script) => {
fetch(script.src)
.then((response) => response.text() )
.then((source) => console.log(source) )


})

我也有同样的问题,所以我这样解决:

  1. Js 文件包含类似
window.someVarForReturn = `content for return`
  1. 在 html 上
<script src="file.js"></script>
<script>console.log(someVarForReturn)</script>

在我的例子中,内容是 html 模板:

  1. 在 js 文件里
window.someVarForReturn = `<did>My template</div>`
  1. 在 html 上
<script src="file.js"></script>
<script>
new DOMParser().parseFromString(someVarForReturn, 'text/html').body.children[0]
</script>

您无法直接获取作为特定脚本标记内容加载的浏览器(安全隐患) ;

但是

您可以再次请求相同的资源(src)(由于缓存的原因,它会立即成功)并读取它的文本:

const scriptSrc = document.querySelector('script#yours').src;
// re-request the same location
const scriptContent = await fetch(scriptSrc).then((res) => res.text());