你能选择包含JavaScript的脚本元素吗?

zzz*_*Bov 5 javascript

可能重复:
我如何引用加载当前正在执行的脚本的脚本标记?

有没有办法选择script包含特定脚本的元素而不给它任何类型的已知属性?

此示例将警告窗口对象,因为它在全局上下文中被调用:

<script>
  alert(this);
</script>
Run Code Online (Sandbox Code Playgroud)

这个例子不会起作用,因为脚本的名称可能会改变(为方便起见,我假设包含了jQuery):

<script type="text/javascript" src="/foo/bar/baz.js"></script>
//baz.js
$('[src^="baz.js"]');
Run Code Online (Sandbox Code Playgroud)

此示例是次优的,因为它依赖于id属性:

<script type="text/javascript" id="foo">
  $('#foo');
</script>
Run Code Online (Sandbox Code Playgroud)

zzz*_*Bov 2

在这种情况下,我很犹豫是否要回答我自己的问题,因为我没有一个 100% 有效的答案,但我已经消除了足够的错误,以获得一个稳定的解决方案。

@Shef 的答案是我想要/需要的一半。

通用 JS 版本:

function getActiveScript()
{
  var s;
  s=document.getElementsByTagName('script');
  return s[s.length - 1];
}
Run Code Online (Sandbox Code Playgroud)

上述代码的问题在于,无论何时执行,它都会选择页面上的最后一个脚本。如果页面加载后包含调用脚本,这将是一个主要问题。

由于我无法直接选择script元素(除非出现另一个解决方案),因此如果在页面加载后添加脚本,我宁愿不选择任何内容。

纯JS答案:

function getActiveScript()
{
  var r,s;
  r = document.readyState;
  if ( r && r != 'complete' )
  {
    s = document.getElementsByTagName('script');
    return s.length ? s[s.length - 1] : null;
  }
  return;
}
Run Code Online (Sandbox Code Playgroud)

在新版本中,document.readyState将进行检查以确保文档尚未完成加载。另外,在document.readyState不使用的浏览器上,它会失败(我想不出现在有什么浏览器使用)。document.readyState

此解决方案的一个警告是,可以将元素动态插入到文档的较早部分,然后在isscript之前执行。如果脚本要使用此代码,它可能会引用错误的. 我还没有检查过这个问题。通常我会添加新的脚本标签(或库中的等效标签),所以这对我来说不是一个大问题。document.readyState'complete'scriptdocument.body.appendChild

另一个可能的漏洞是在调用document.body 之前 是否附加了新脚本。getActiveScript同样,我还没有测试过它,但这可能意味着最后选择的脚本的计算结果与正在执行的脚本不同。


实际使用情况:

有人问我为什么要选择当前评估的脚本元素。虽然“因为我可以”可能会被理解,但我确实合法的理由想要使用这个特性/功能/肮脏的黑客。

我创建了一个(几个)jQuery 插件来完成我最初想要的事情。

jQuery 插件:jquery.activescript.js

(function($){
  "use strict";
  $.activeScript = function(){
    var r;
    r=document.readyState;
    return r && r != 'complete' ? $('script:last') : $();
  };
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

jQuery 插件:jquery.activescript.plugin.js

默认情况下适用于 jQuery UI

(function($){
  "use strict";
  var plugins,d,p,$p;
  d = $.activeScript().data();
  plugins = d.plugins || 'draggable droppable resizable selectable sortable accordion autocomplete button datepicker dialog progressbar slider tabs';
  plugins=plugins.split(' ');
  $(function(){
    while(p=plugins.pop())
    {
      $p=$(d[p+'Selector']);
      if ($p[p])$p[p]();
    }
  });
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

您使用的方式jquery.activescript.plugin.js如下:

<script type="text/javascript" src="jquery.activescript.plugin.js"
  data-draggable-selector=".draggable.default"
  data-droppable-selector=".droppable.default"
  data-resizable-selector=".resizable.default"
  data-selectable-selector=".selectable.default"
  data-sortable-selector=".sortable.default"
  data-accordion-selector=".accordion.default"
  data-autocomplete-selector=".autocomplete.default"
  data-button-selector=".button.default"
  data-datepicker-selector=".datepicker.default"
  data-dialog-selector=".dialog.default"
  data-progressbar-selector=".progressbar.default"
  data-slider-selector=".slider.default"
  data-tabs-selector=".tabs.default"></script>
Run Code Online (Sandbox Code Playgroud)

这将允许您在语义上将默认插件绑定到您的页面,而无需在 JS 文件中进行修改。如果需要非默认值,您应该在 JS 文件中进行修改,因此我没有添加任何指定选项的机制(尽管有一些插件确实可以使用它)。

activescript独立插件可以使用相同的基本机制来更简单地覆盖默认值。