使用JavaScript来阻止评估后续的< script>标记? [英] Use JavaScript to prevent a later `<script>` tag from being evaluated?

查看:90
本文介绍了使用JavaScript来阻止评估后续的< script>标记?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个古怪的用例,但我有我的理由:

我希望能够写入

 < script type =text / javascriptsrc =first.js>< / script> 
< script type =text / javascriptsrc =second.js>< / script>

在我的标记中,并使用 first.js ,防止或延迟执行 second.js 。这是可能的,在任何浏览器?如果 first.js 的内容是内联的呢? (如果有帮助,假设第二个脚本标记具有 id 属性。)



因为我已经得到我应该澄清一些答案,我应该澄清:


  1. 解决方案必须完全在 first.js 。任何需要更改页面原始HTML或 second.js 的内容都是不可接受的。

  2. 可以通过Ajax加载 second.js 并使用 eval 执行。这是很容易的部分。困难的部分是阻止立即执行 second.js

  3. 假设您不知道 second.js 中的内容。所以,你不能用一个无操作函数来替换由 second.js 调用的每个全局函数。 (另外,这几乎肯定会导致错误。)

如果您知道某种解决方案适用于某些浏览器,但不适用于其他浏览器,我很乐意听到它。



示例:为了更具体一点,我们假设代码

 < script type =text / javascript> 
函数func(){
window.meaningOfLife = 42;
window.loadSecond();
};
setTimeout(func,10);
< / script>

在两个脚本 includes之前, second.js 包含行

  if(window.meaningOfLife!= = 42){throw new Error();} 

first.js 应该能够通过延迟 second.js 执行直到 window.loadSecond 来防止这个错误。运行。 (假设 window.loadSecond 的实现也在 first.js 中)。 允许触摸 window.meaningOfLife



更新:Alohci的答案符合的要求,但仅限于第二个脚本标记在第一个之后立即 ,而两者之间只有空格。如果有人可以扩展他的黑客以避免这种要求,而不会引入其他不必要的后果,那将是惊人的...... 您的具体要求设置,这实际上很简单,应该完全跨浏览器工作。然而,它需要first.js立即在second.js之前,除了空格之外没有任何东西。

首先,我们假设HTML看起来像这样:

p>

 <!DOCTYPE html> 
< html>
< head>
< title>测试用例< / title>
< meta charset =UTF-8/>
< script type =text / javascript>
函数func(){
window.meaningOfLife = 42;
window.loadSecond();
};
< / script>
< script type =text / javascriptsrc =first.js>< / script>
< script type =text / javascriptsrc =second.js>< / script>
< / head>
< body>
< p> Lorem ipsum dolor sit amet ...< / p>
< a href =javascript:func()>运行Func()< / a>
< / body>
< / html>

我已经删除了setTimeout,因为这会导致func()在start.js运行之前运行loadSecond未定义错误。相反,我提供了一个要点击的锚来运行func()。第二,假设second.js如下所示:

  document.body.appendChild(document.createTextNode(second.js has run。)); 
if(window.meaningOfLife!== 42){throw new Error();}

在这里,我刚刚添加了一行来添加一些文本到文档主体,以便更容易看到second.js实际运行的时间。



然后first.js的解决方案是这样的:

$ p $ function loadSecond()
{
var runSecond = document。的createElement( 脚本);
runSecond.setAttribute(src,second.js);
document.body.appendChild(runSecond);


document.write(< script type ='application / x-suppress'>);

当func()运行时,loadSecond函数就在那里运行second.js。



解决方案的关键在于 document.write 行。它将注入到first.js的close脚本标记和第二个脚本标记之间的HTML < script type ='application / x-suppress'> 之间。 js。



解析器将会看到它并开始一个新的脚本元素。由于type属性的值不是浏览器认为是JavaScript的值,因此它不会尝试运行其内容。 (因此,您可以在此处使用无限数量的可能的类型属性值,但您必须包含类型属性,因为如果不存在,浏览器会假定该脚本的内容是JavaScript。)



second.js脚本的开始标记将被解析为新脚本元素的文本内容,但不会执行。最后,second.js脚本的结束标记将被重新用于关闭新的脚本元素,这意味着HTML的其余部分将被正确解析。



您可以在 http://www.alohci.net/static/jsprevent/jsprevent上查看工作版本。 htm


This is a bit of an oddball use case, but I have my reasons:

I'd like to be able to write

<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>

in my markup and, using the code in first.js, prevent or delay the execution of second.js. Is this possible, in any browser? What if the contents of first.js are inlined? (If it helps, assume that the second script tag has an id attribute.)

Since I've gotten a couple of answers that missed what I'm getting at, I should clarify:

  1. The solution must be entirely within first.js. Anything that require changes to the original HTML of the page, or to second.js, is not acceptable.
  2. It is acceptable to load second.js via Ajax and execute it using eval. That's the easy part. The hard part is preventing the immediate execution of second.js.
  3. Assume that you don't know what's in second.js. So, you can't just replace each global function called by second.js with a no-op function. (Plus, this would almost certainly lead to errors.)

If you know of a solution that works in some browsers but not in others, I'd love to hear it.

Example: To make this a little more concrete, let's say that the code

<script type="text/javascript">
  function func() {
    window.meaningOfLife = 42;
    window.loadSecond();
  };
  setTimeout(func, 10);
</script>

precedes the two script includes, and that second.js contains the line

if (window.meaningOfLife !== 42) {throw new Error();}

first.js should be able to prevent this error by delaying second.js from executing until window.loadSecond is run. (Assume the implementation of window.loadSecond is also in first.js.) It is not allowed to touch window.meaningOfLife.

Update: Alohci's answer meets these requirements, but only on the condition that the second script tag comes immediately after the first, with nothing but whitespace in between. If someone could extend his hack to avoid that requirement, without introducing other unwanted consequences, that would be amazing...

解决方案

Given your specific requirements set, this is actually quite simple and should work completely cross-browser. It does require however, that first.js immediately precedes second.js without anything between them except white space.

First, let's assume that the HTML looks like this:

<!DOCTYPE html>
<html>
  <head>
    <title>Test Case</title>
    <meta charset="UTF-8" />
    <script type="text/javascript">
      function func() {
        window.meaningOfLife = 42;
        window.loadSecond();
      };
    </script>
    <script type="text/javascript" src="first.js"></script>
    <script type="text/javascript" src="second.js"></script>
  </head>
  <body>
    <p>Lorem ipsum dolor sit amet ...</p>
    <a href="javascript:func()">Run Func()</a>
  </body>
</html>

I've removed the setTimeout because that can cause func() to run before start.js runs causing a "loadSecond is not defined" error. Instead, I've provided an anchor to be clicked on to run func().

Second, let's assume that second.js looks like this:

document.body.appendChild(document.createTextNode("second.js has run. "));
if (window.meaningOfLife !== 42) {throw new Error();}

Here, I've just added a line to append some text to the document body, so that it is easier to see when second.js actually runs.

Then the solution for first.js is this:

function loadSecond()
{
    var runSecond = document.createElement("script");
    runSecond.setAttribute("src", "second.js"); 
    document.body.appendChild(runSecond);
}

document.write("<script type='application/x-suppress'>");

The loadSecond function is just there to run second.js when func() runs.

The key to the solution is the document.write line. It will inject into the HTML <script type='application/x-suppress'> between the close script tag of first.js and the open script tag of second.js.

The parser will see this and start a new script element. Because the type attribute has a value which is not one that the browser recognises as being JavaScript, it will not attempt to run its content. (So there are an infinite number of possible type attribute values you could use here, but you must include a type attribute, as in its absence, the browser will assume that the script's content is JavaScript.)

The second.js script's opening tag will then be parsed as text content of the new script element and not executed. Finally the second.js script's closing tag will be re-purposed to close the new script element instead, which means that the remainder of the HTML is parsed correctly.

You can see a working version at http://www.alohci.net/static/jsprevent/jsprevent.htm

这篇关于使用JavaScript来阻止评估后续的&lt; script&gt;标记?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆