如何引用加载当前执行脚本的脚本标签?

发布于 2025-02-04 18:45:14 字数 920 浏览 3 评论 0原文

如何引用加载当前正在运行的JavaScript的脚本元素?

这是情况。我有一个“主”脚本在页面上加载高,第一件事在Head Tag下。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type="text/javascript" src="scripts.js"></script>

“ scripts.js”中有一个脚本,需要能够对其他脚本进行按需加载。普通方法对我不太有用,因为我需要添加新脚本而不引用HEAD标签,因为Head元素尚未完成渲染:

document.getElementsByTagName('head')[0].appendChild(v);

我想做的是引用加载当前脚本的脚本元素以便然后,我可以将新的新型脚本标签附加到DOM之后。

<script type="text/javascript" src="scripts.js"></script>
loaded by scripts.js--><script type="text/javascript" src="new_script1.js"></script>
loaded by scripts.js --><script type="text/javascript" src="new_script2.js"></script>

How can I reference the script element that loaded the javascript that is currently running?

Here's the situation. I have a "master" script being loaded high in the page, first thing under the HEAD tag.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type="text/javascript" src="scripts.js"></script>

There is a script in "scripts.js" which needs to be able to do on-demand loading of other scripts. The normal method doesn't quite work for me because I need to add new scripts without referencing the HEAD tag, because the HEAD element hasn't finished rendering:

document.getElementsByTagName('head')[0].appendChild(v);

What I want to do is reference the script element that loaded the current script so that I can then append my new dynamically loaded script tags into the DOM after it.

<script type="text/javascript" src="scripts.js"></script>
loaded by scripts.js--><script type="text/javascript" src="new_script1.js"></script>
loaded by scripts.js --><script type="text/javascript" src="new_script2.js"></script>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

关于从前 2025-02-11 18:45:14

如何获取当前脚本元素:

1。使用document.currentscript

document.currentscript 将返回&lt; script&gt;当前正在处理其脚本的元素。

<script>
var me = document.currentScript;
</script>

好处

  • 简单明了。可靠的。
  • 无需修改脚本标签
  • 与异步脚本(defer&amp; async)一起
  • 使用,与脚本插入的脚本插入动态

问题

  • 在较旧的浏览器和IE中无法使用。
  • 不使用模块&lt; script type =“ module”&gt;

2。通过id

给出脚本的脚本ID属性将允许您从内部使用iD

<script id="myscript">
var me = document.getElementById('myscript');
</script>

好处

  • 简单明了。可靠的。
  • 几乎普遍支持的
  • 使用异步脚本(defer&amp; async
  • 与脚本插入的脚本工作需要动态

问题,

  • 需要将自定义属性添加到脚本标签
  • code> ID 属性可能会在某些边缘情况3中引起某些浏览器中脚本的怪异行为

3。使用data - *属性选择脚本

- 属性给脚本a data - * 属性将让您轻松地从内部选择它。

<script data-name="myscript">
var me = document.querySelector('script[data-name="myscript"]');
</script>

这比上一个选项几乎没有好处。

好处

  • 简单明了。
  • 使用异步脚本(defer&amp; async
  • 与脚本一起工作,插入了动态

问题,

  • 需要将自定义属性添加到脚本标签
  • html5和queryselector(queryselector)()代码>
  • 与使用id属性相比,所有浏览器中不符合所有浏览器的支持,
  • 都将围绕&lt; script&gt;带有id> id> id edge案例。
  • 如果另一个元素在页面上具有相同的数据属性和值,可能会感到困惑。

4。选择SRC的脚本

而不是使用数据属性,可以使用选择器来选择脚本由源选择脚本:

<script src="//example.com/embed.js"></script>

in embed.js:

var me = document.querySelector('script[src="//example.com/embed.js"]');

felasion

  • felasial可靠
  • 与异步脚本一起使用(defer defer&amp; amp; async
  • 与脚本一起插入的脚本
  • 无需自定义属性或ID

问题

  • 而不是对本地脚本的工作
  • 将在不同环境中引起问题,例如开发和生产
  • 静态和脆弱。 更改脚本文件的位置将需要修改脚本所支持的脚本
  • 与使用id属性相比,
  • 不足,如果您两次加载相同的脚本

5 还可以循环浏览每个脚本元素,并单独检查每个脚本以选择我们想要的一个元素:

<script>
var me = null;
var scripts = document.getElementsByTagName("script")
for (var i = 0; i < scripts.length; ++i) {
    if( isMe(scripts[i])){
      me = scripts[i];
    }
}
</script>

这使我们可以在不支持queryselector()均与属性的旧浏览器中使用以前的两种技术。例如:

function isMe(scriptElem){
    return scriptElem.getAttribute('src') === "//example.com/embed.js";
}

这继承了采用的任何方法的好处和问题,但不依赖querySelector(),因此可以在较旧的浏览器中工作。

6.获得最后执行的脚本,

因为脚本是顺序执行的,最后一个脚本元素通常是当前运行的脚本:

<script>
var scripts = document.getElementsByTagName( 'script' );
var me = scripts[ scripts.length - 1 ];
</script>

益处

  • 简单。
  • 几乎普遍支持
  • 任何自定义属性或ID问题

的问题

  • 与异步脚本(defer&amp; code> async )一起使用
  • 不使用动态插入脚本的工作

How to get the current script element:

1. Use document.currentScript

document.currentScript will return the <script> element whose script is currently being processed.

<script>
var me = document.currentScript;
</script>

Benefits

  • Simple and explicit. Reliable.
  • Don't need to modify the script tag
  • Works with asynchronous scripts (defer & async)
  • Works with scripts inserted dynamically

Problems

  • Will not work in older browsers and IE.
  • Does not work with modules <script type="module">

2. Select script by id

Giving the script an id attribute will let you easily select it by id from within using document.getElementById().

<script id="myscript">
var me = document.getElementById('myscript');
</script>

Benefits

  • Simple and explicit. Reliable.
  • Almost universally supported
  • Works with asynchronous scripts (defer & async)
  • Works with scripts inserted dynamically

Problems

  • Requires adding a custom attribute to the script tag
  • id attribute may cause weird behaviour for scripts in some browsers for some edge cases

3. Select the script using a data-* attribute

Giving the script a data-* attribute will let you easily select it from within.

<script data-name="myscript">
var me = document.querySelector('script[data-name="myscript"]');
</script>

This has few benefits over the previous option.

Benefits

  • Simple and explicit.
  • Works with asynchronous scripts (defer & async)
  • Works with scripts inserted dynamically

Problems

  • Requires adding a custom attribute to the script tag
  • HTML5, and querySelector() not compliant in all browsers
  • Less widely supported than using the id attribute
  • Will get around <script> with id edge cases.
  • May get confused if another element has the same data attribute and value on the page.

4. Select the script by src

Instead of using the data attributes, you can use the selector to choose the script by source:

<script src="//example.com/embed.js"></script>

In embed.js:

var me = document.querySelector('script[src="//example.com/embed.js"]');

Benefits

  • Reliable
  • Works with asynchronous scripts (defer & async)
  • Works with scripts inserted dynamically
  • No custom attributes or id needed

Problems

  • Does not work for local scripts
  • Will cause problems in different environments, like Development and Production
  • Static and fragile. Changing the location of the script file will require modifying the script
  • Less widely supported than using the id attribute
  • Will cause problems if you load the same script twice

5. Loop over all scripts to find the one you want

We can also loop over every script element and check each individually to select the one we want:

<script>
var me = null;
var scripts = document.getElementsByTagName("script")
for (var i = 0; i < scripts.length; ++i) {
    if( isMe(scripts[i])){
      me = scripts[i];
    }
}
</script>

This lets us use both previous techniques in older browsers that don't support querySelector() well with attributes. For example:

function isMe(scriptElem){
    return scriptElem.getAttribute('src') === "//example.com/embed.js";
}

This inherits the benefits and problems of whatever approach is taken, but does not rely on querySelector() so will work in older browsers.

6. Get the last executed script

Since the scripts are executed sequentially, the last script element will very often be the currently running script:

<script>
var scripts = document.getElementsByTagName( 'script' );
var me = scripts[ scripts.length - 1 ];
</script>

Benefits

  • Simple.
  • Almost universally supported
  • No custom attributes or id needed

Problems

  • Does not work with asynchronous scripts (defer & async)
  • Does not work with scripts inserted dynamically
っ左 2025-02-11 18:45:14

由于脚本是顺序执行的,因此当前执行的脚本标签始终是页面上的最后一个脚本标签。因此,要获取脚本标签,您可以做:

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

Since scripts are executed sequentially, the currently executed script tag is always the last script tag on the page until then. So, to get the script tag, you can do:

var scripts = document.getElementsByTagName( 'script' );
var thisScriptTag = scripts[ scripts.length - 1 ];
缱倦旧时光 2025-02-11 18:45:14

最简单的事情可能是给您的脚本标签一个id属性。

Probably the easiest thing to do would be to give your scrip tag an id attribute.

万人眼中万个我 2025-02-11 18:45:14

这是利用document.currentscript的polyfill,如果它存在并落后于通过ID查找脚本。

<script id="uniqueScriptId">
    (function () {
        var thisScript = document.CurrentScript || document.getElementByID('uniqueScriptId');

        // your code referencing thisScript here
    ());
</script>

如果您将其包含在每个脚本标签的顶部,我相信您将能够始终知道要触发哪个脚本标签,并且您还可以在异步回调的上下文中引用脚本标签。

未经测试,因此如果您尝试的话,请留给他人。

Here's a bit of a polyfill that leverages document.CurrentScript if it exists and falls back to finding the script by ID.

<script id="uniqueScriptId">
    (function () {
        var thisScript = document.CurrentScript || document.getElementByID('uniqueScriptId');

        // your code referencing thisScript here
    ());
</script>

If you include this at the top of every script tag I believe you'll be able to consistently know which script tag is being fired, and you'll also be able to reference the script tag in the context of an asynchronous callback.

Untested, so leave feedback for others if you try it.

任谁 2025-02-11 18:45:14

脚本仅在没有“延期”或“ async”属性的情况下顺序执行。在这种情况下,了解脚本标签的可能ID/SRC/标题属性之一。因此,格雷格和贾斯汀的建议都是正确的。

WhatWG列表上的document.currentscript已经有一个建议。

编辑:Firefox&gt; 4已经实现了此非常有用的属性,但它在IE11中没有可用,我在Chrome 29和Safari 8中仅可用

。以下可能是获得当前运行脚本的良好交叉浏览器替代方案:

var me = document.scripts[document.scripts.length -1];

Script are executed sequentially only if they do not have either a "defer" or an "async" attribute. Knowing one of the possible ID/SRC/TITLE attributes of the script tag could work also in those cases. So both Greg and Justin suggestions are correct.

There is already a proposal for a document.currentScript on the WHATWG lists.

EDIT: Firefox > 4 already implement this very useful property but it is not available in IE11 last I checked and only available in Chrome 29 and Safari 8.

EDIT: Nobody mentioned the "document.scripts" collection but I believe that the following may be a good cross browser alternative to get the currently running script:

var me = document.scripts[document.scripts.length -1];
说不完的你爱 2025-02-11 18:45:14

它必须在页面加载和添加JavaScript(ex。with ajax)时使用脚本标签时工作

<script id="currentScript">
var $this = document.getElementById("currentScript");
$this.setAttribute("id","");
//...
</script>

It must works at page load and when an script tag is added with javascript (ex. with ajax)

<script id="currentScript">
var $this = document.getElementById("currentScript");
$this.setAttribute("id","");
//...
</script>
苹果你个爱泡泡 2025-02-11 18:45:14

请按照以下简单步骤获取对当前执行脚本块的引用:

  1. 将一些随机唯一的字符串在脚本块中放置(在每个脚本块中必须是唯一 /不同的)
  2. intume.getElementsbytagname('script'),从它们的每个内容(从Innertext/TextContent属性获得)。

示例(abcde345678是唯一的ID)

<script type="text/javascript">
var A=document.getElementsByTagName('script'),i=count(A),thi$;
for(;i;thi$=A[--i])
  if((thi$.innerText||thi$.textContent).indexOf('ABCDE345678'))break;
// Now thi$ is refer to current script block
</script>

顺便说一句,对于您的情况,您可以简单地使用opersed document.write.write.write.write()方法包含另一个脚本。
正如您提到的那样,DOM尚未渲染,您可以从浏览器始终以线性序列执行脚本(除了延期将呈现的脚本)以下事实,因此您的文档的其余部分仍然“不存在”。
您通过document.write()编写的任何内容都将在呼叫者脚本之后放置。

原始HTML页面的示例

<!doctype html>
<html><head>
<script src="script.js"></script>
<script src="otherscript.js"></script>
<body>anything</body></html>

脚本的内容

document.write('<script src="inserted.js"></script>');

渲染后,DOM结构将成为:

HEAD
  SCRIPT script.js
  SCRIPT inserted.js
  SCRIPT otherscript.js
BODY

Follow these simple steps to obtain reference to current executing script block:

  1. Put some random unique string within the script block (must be unique / different in each script block)
  2. Iterate result of document.getElementsByTagName('script'), looking the unique string from each of their content (obtained from innerText/textContent property).

Example (ABCDE345678 is the unique ID):

<script type="text/javascript">
var A=document.getElementsByTagName('script'),i=count(A),thi$;
for(;i;thi$=A[--i])
  if((thi$.innerText||thi$.textContent).indexOf('ABCDE345678'))break;
// Now thi$ is refer to current script block
</script>

btw, for your case, you can simply use old fashioned document.write() method to include another script.
As you mentioned that DOM is not rendered yet, you can take advantage from the fact that browser always execute script in linear sequence (except for deferred one that will be rendered later), so the rest of your document is still "not exists".
Anything you write through document.write() will be placed right after the caller script.

Example of original HTML page:

<!doctype html>
<html><head>
<script src="script.js"></script>
<script src="otherscript.js"></script>
<body>anything</body></html>

Content of script.js:

document.write('<script src="inserted.js"></script>');

After rendered, the DOM structure will become:

HEAD
  SCRIPT script.js
  SCRIPT inserted.js
  SCRIPT otherscript.js
BODY
痞味浪人 2025-02-11 18:45:14

要获取当前加载脚本的脚本,您可以使用

var thisScript = document.currentScript;

您需要在脚本开头保留参考的脚本,因此您可以稍后致电

var url = thisScript.src

To get the script, that currently loaded the script you can use

var thisScript = document.currentScript;

You need to keep a reference at the beginning of your script, so you can call later

var url = thisScript.src
几味少女 2025-02-11 18:45:14

一种处理异步的方法延期脚本是利用Onload处理程序 - 为所有脚本标签设置一个Onload处理程序,而执行第一个应该是您的脚本标签。

function getCurrentScript(callback) {
  if (document.currentScript) {
    callback(document.currentScript);
    return;
  }
  var scripts = document.scripts;
  function onLoad() {
    for (var i = 0; i < scripts.length; ++i) {
      scripts[i].removeEventListener('load', onLoad, false);
    }
    callback(event.target);
  }
  for (var i = 0; i < scripts.length; ++i) {
    scripts[i].addEventListener('load', onLoad, false);
  }
}

getCurrentScript(function(currentScript) {
  window.console.log(currentScript.src);
});

An approach for dealing with async & deferred scripts is to leverage the onload handler- set an onload handler for all script tags and the first one which executes should be yours.

function getCurrentScript(callback) {
  if (document.currentScript) {
    callback(document.currentScript);
    return;
  }
  var scripts = document.scripts;
  function onLoad() {
    for (var i = 0; i < scripts.length; ++i) {
      scripts[i].removeEventListener('load', onLoad, false);
    }
    callback(event.target);
  }
  for (var i = 0; i < scripts.length; ++i) {
    scripts[i].addEventListener('load', onLoad, false);
  }
}

getCurrentScript(function(currentScript) {
  window.console.log(currentScript.src);
});
春花秋月 2025-02-11 18:45:14

考虑此算法。当您的脚本加载(如果有多个相同的脚本)时,请浏览文档。订阅,查找具有正确的“ SRC”属性的第一个脚本,并保存并将其标记为“访问'',并使用data-Attribute或unique className标记为“访问”。

当下一个脚本加载时,再次扫描文档。记录再次传递已经标记为访问的所有脚本。以该脚本的第一个未访问的实例。

这是假设相同的脚本可能会按照从头到尾从顶部到底部从同步到异步的顺序执行。

(function () {
  var scripts = document.scripts;

  // Scan for this data-* attribute
  var dataAttr = 'data-your-attribute-here';

  var i = 0;
  var script;
  while (i < scripts.length) {
    script = scripts[i];
    if (/your_script_here\.js/i.test(script.src)
        && !script.hasAttribute(dataAttr)) {

        // A good match will break the loop before
        // script is set to null.
        break;
    }

    // If we exit the loop through a while condition failure,
    // a check for null will reveal there are no matches.
    script = null;
    ++i;
  }

  /**
   * This specific your_script_here.js script tag.
   * @type {Element|Node}
   */
  var yourScriptVariable = null;

  // Mark the script an pass it on.
  if (script) {
    script.setAttribute(dataAttr, '');
    yourScriptVariable = script;
  }
})();

这将扫描所有脚本的第一个匹配脚本,该脚本没有特殊属性标记。

然后用数据属性标记该节点(如果发现),以便随后的扫描不会选择它。这类似于图形遍历BFS和DFS算法,在该算法中,节点可以标记为“访问”以防止重新访问。

Consider this algorithm. When your script loads (if there are multiple identical scripts), look through document.scripts, find the first script with the correct "src" attribute, and save it and mark it as 'visited' with a data-attribute or unique className.

When the next script loads, scan through document.scripts again, passing over any script already marked as visited. Take the first unvisited instance of that script.

This assumes that identical scripts will likely execute in the order in which they are loaded, from head to body, from top to bottom, from synchronous to asynchronous.

(function () {
  var scripts = document.scripts;

  // Scan for this data-* attribute
  var dataAttr = 'data-your-attribute-here';

  var i = 0;
  var script;
  while (i < scripts.length) {
    script = scripts[i];
    if (/your_script_here\.js/i.test(script.src)
        && !script.hasAttribute(dataAttr)) {

        // A good match will break the loop before
        // script is set to null.
        break;
    }

    // If we exit the loop through a while condition failure,
    // a check for null will reveal there are no matches.
    script = null;
    ++i;
  }

  /**
   * This specific your_script_here.js script tag.
   * @type {Element|Node}
   */
  var yourScriptVariable = null;

  // Mark the script an pass it on.
  if (script) {
    script.setAttribute(dataAttr, '');
    yourScriptVariable = script;
  }
})();

This will scan through all the script for the first matching script that isn't marked with the special attribute.

Then mark that node, if found, with a data-attribute so subsequent scans won't choose it. This is similar to graph traversal BFS and DFS algorithms where nodes may be marked as 'visited' to prevent revisitng.

愛放△進行李 2025-02-11 18:45:14

我有这个,它在FF3,IE6&amp;中工作。 7。在按需加载脚本中的方法直到完成页面加载才能完成,但这仍然非常有用。

//handle on-demand loading of javascripts
makescript = function(url){
    var v = document.createElement('script');
    v.src=url;
    v.type='text/javascript';

    //insertAfter. Get last <script> tag in DOM
    d=document.getElementsByTagName('script')[(document.getElementsByTagName('script').length-1)];
    d.parentNode.insertBefore( v, d.nextSibling );
}

I've got this, which is working in FF3, IE6 & 7. The methods in the on-demand loaded scripts aren't available until page load is complete, but this is still very useful.

//handle on-demand loading of javascripts
makescript = function(url){
    var v = document.createElement('script');
    v.src=url;
    v.type='text/javascript';

    //insertAfter. Get last <script> tag in DOM
    d=document.getElementsByTagName('script')[(document.getElementsByTagName('script').length-1)];
    d.parentNode.insertBefore( v, d.nextSibling );
}
滿滿的愛 2025-02-11 18:45:14

如果您可以假设脚本的文件名,则可以找到它。到目前为止,我只真正在Firefox中测试了以下功能。

  function findMe(tag, attr, file) {
    var tags = document.getElementsByTagName(tag);
    var r = new RegExp(file + '
);
    for (var i = 0;i < tags.length;i++) {
      if (r.exec(tags[i][attr])) {
        return tags[i][attr];
      }
    }
  };
  var element = findMe('script', 'src', 'scripts.js');

If you can assume the file name of the script, you can find it. I've only really tested the following function in Firefox so far.

  function findMe(tag, attr, file) {
    var tags = document.getElementsByTagName(tag);
    var r = new RegExp(file + '
);
    for (var i = 0;i < tags.length;i++) {
      if (r.exec(tags[i][attr])) {
        return tags[i][attr];
      }
    }
  };
  var element = findMe('script', 'src', 'scripts.js');
红颜悴 2025-02-11 18:45:14

我正在使用此常用的eval的常规替代方案插入脚本标签,然后直接在添加到DOM之前设置全局属性 currentComponentscript 。

  const old = el.querySelector("script")[0];
  const replacement = document.createElement("script");
  replacement.setAttribute("type", "module");
  replacement.appendChild(document.createTextNode(old.innerHTML));
  window.currentComponentScript = replacement;
  old.replaceWith(replacement);

不过循环无法工作。 DOM直到下一个宏观施法才能运行脚本,因此其中一批只能看到最后一个值集。您必须settimeout整个段落,然后settimeout在上一个完成后的下一个。 IE链条链,不仅是从循环中多次调用settimeout

I was inserting script tags dynamically with this usual alternative to eval and simply set a global property currentComponentScript right before adding to the DOM.

  const old = el.querySelector("script")[0];
  const replacement = document.createElement("script");
  replacement.setAttribute("type", "module");
  replacement.appendChild(document.createTextNode(old.innerHTML));
  window.currentComponentScript = replacement;
  old.replaceWith(replacement);

Doesn't work in a loop though. The DOM doesn't run the scripts until the next macrotask so a batch of them will only see the last value set. You'd have to setTimeout the whole paragraph, and then setTimeout the next one after the previous finishes. I.e. chain the setTimeouts, not just call setTimeout multiple times in a row from a loop.

触ぅ动初心 2025-02-11 18:45:14

为什么不看堆栈?

function getURL()
{
 var obj = {};
 Error.captureStackTrace(obj, getURL);

 let ret=obj.stack.split('(')[1].split(')')[0];
 return ret.split(':',ret.split(':').length-2).join(':');
};

console.log(getURL());

Why not look into the stack?

function getURL()
{
 var obj = {};
 Error.captureStackTrace(obj, getURL);

 let ret=obj.stack.split('(')[1].split(')')[0];
 return ret.split(':',ret.split(':').length-2).join(':');
};

console.log(getURL());
向地狱狂奔 2025-02-11 18:45:14

我发现以下代码是最一致,表现和简单的。

var scripts = document.getElementsByTagName('script');
var thisScript = null;
var i = scripts.length;
while (i--) {
  if (scripts[i].src && (scripts[i].src.indexOf('yourscript.js') !== -1)) {
    thisScript = scripts[i];
    break;
  }
}
console.log(thisScript);

I have found the following code to be the most consistent, performant, and simple.

var scripts = document.getElementsByTagName('script');
var thisScript = null;
var i = scripts.length;
while (i--) {
  if (scripts[i].src && (scripts[i].src.indexOf('yourscript.js') !== -1)) {
    thisScript = scripts[i];
    break;
  }
}
console.log(thisScript);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文