为什么在使用document.write()?</script>编写<script>标记时将其拆分

时间:2008-10-25 07:58:56

标签: javascript html

为什么有些网站(或为客户提供javascript代码的广告客户)会采用在<script>次来电中分割</script>和/或document.write()代码的技术?

我注意到亚马逊也这样做,例如:

<script type='text/javascript'>
  if (typeof window['jQuery'] == 'undefined') document.write('<scr'+'ipt type="text/javascript" src="http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></sc'+'ript>');
</script>

5 个答案:

答案 0 :(得分:361)

</script>必须被拆分,否则它会过早地结束封闭的<script></script>块。实际上应该在</之间进行拆分,因为假定脚本块(根据SGML)为terminated by any end-tag open (ETAGO) sequence (i.e. </)

  

尽管STYLE和SCRIPT元素使用CDATA作为其数据模型,但对于这些元素,CDATA必须由用户代理以不同方式处理。必须将标记和实体视为原始文本并按原样传递给应用程序。第一次出现的字符序列“</”(结束标记打开定界符)被视为终止元素内容的结尾。在有效文档中,这将是元素的结束标记。

但实际上,浏览器只会在实际的</script>关闭标记上解析CDATA脚本块。

在XHTML中,脚本块没有这种特殊处理,因此其中的任何<(或&)字符必须与任何其他元素中的&escaped;一样。然而,将XHTML解析为旧式HTML的浏览器会变得混乱。有一些涉及CDATA块的解决方法,但最简单的方法是避免使用未转义的这些字符。从适用于任何类型的解析器的脚本编写脚本元素的更好方法是:

<script type="text/javascript">
    document.write('\x3Cscript type="text/javascript" src="foo.js">\x3C/script>');
</script>

答案 1 :(得分:29)

这是我想要生成内联脚本标记时使用的另一种变体(因此它立即执行),而不需要任何形式的转义:

<script>
    var script = document.createElement('script');
    script.src = '/path/to/script.js';
    document.write(script.outerHTML);
</script>

(注意:与网络上的大多数示例相反,我没有在封闭标签上设置type="text/javascript",也没有在生成的标签上设置{没有浏览器没有将其作为默认值,因此它是多余的,但如果你不同意也不会伤害。)

答案 2 :(得分:20)

我认为是为了防止浏览器的HTML解析器解释&lt; script&gt;,主要是&lt; / script&gt;作为实际脚本的结束标记,但我不认为使用document.write是评估脚本块的绝佳主意,为什么不使用DOM ...

var newScript = document.createElement("script");
...

答案 3 :(得分:8)

Bobince发布的解决方案非常适合我。我想为未来的访问者提供另一种方法:

if (typeof(jQuery) == 'undefined') {
    (function() {
        var sct = document.createElement('script');
        sct.src = ('https:' == document.location.protocol ? 'https' : 'http') +
          '://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js';
        sct.type = 'text/javascript';
        sct.async = 'true';
        var domel = document.getElementsByTagName('script')[0];
        domel.parentNode.insertBefore(sct, domel);
    })();
}

在这个例子中,我为jQuery包含了一个条件加载来演示用例。希望这对某人有用!

答案 4 :(得分:8)

Javascript字符串litteral中的</script>被HTML解析器解释为结束标记,从而导致意外行为(see example on JSFiddle)。

为了避免这种情况,你可以将你的javascript放在注释之间(这种编码风格是常见的做法,当Javascript在浏览器中得不到支持时)。这可行(see example in JSFiddle):

<script type="text/javascript">
    <!--
    if (jQuery === undefined) {
        document.write('<script type="text/javascript" src="http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js"></script>');
    }
    // -->
</script>

...但说实话,使用document.write并不是我认为最好的做法。为什么不直接操纵DOM?

<script type="text/javascript">
    <!--
    if (jQuery === undefined) {
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', 'http://z-ecx.images-amazon.com/images/G/01/javascripts/lib/jquery/jquery-1.2.6.pack._V265113567_.js');
        document.body.appendChild(script);
    }
    // -->
</script>